From 526f86d08529aa8f501cb015c1e442aa743940da Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 21 Aug 2016 03:16:00 -0700 Subject: [PATCH] 3DS: Implement adjustable filtering and sprite rotation --- CHANGES | 1 + src/platform/3ds/CMakeLists.txt | 53 ++++--------- src/platform/3ds/ctr-gpu.c | 64 ++++++++-------- src/platform/3ds/ctr-gpu.h | 4 +- src/platform/3ds/gui-font.c | 20 ++++- src/platform/3ds/main.c | 125 ++++++++++++++++++++++++++----- src/platform/3ds/uishader.g.pica | 95 ++++++++++++++--------- src/platform/3ds/uishader.v.pica | 6 +- 8 files changed, 235 insertions(+), 133 deletions(-) diff --git a/CHANGES b/CHANGES index a02639260..0c418e560 100644 --- a/CHANGES +++ b/CHANGES @@ -66,6 +66,7 @@ Misc: - Util: Add Vector GetConstPointer - Util: Add rtrim - GBA Memory: Optimize Load-/StoreMultiple + - 3DS: Adjustable filering 0.4.1: (2016-07-11) Bugfixes: diff --git a/src/platform/3ds/CMakeLists.txt b/src/platform/3ds/CMakeLists.txt index 8546835e4..fb3501bc5 100644 --- a/src/platform/3ds/CMakeLists.txt +++ b/src/platform/3ds/CMakeLists.txt @@ -30,12 +30,9 @@ set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) list(APPEND GUI_SRC ${CMAKE_CURRENT_BINARY_DIR}/icons.c - ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.c - ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h - ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h - ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.c - ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.h - ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.shbin.h + ${CMAKE_CURRENT_BINARY_DIR}/uishader.c + ${CMAKE_CURRENT_BINARY_DIR}/uishader.h + ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin.h ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c ${CMAKE_CURRENT_SOURCE_DIR}/ctr-gpu.c @@ -43,12 +40,9 @@ list(APPEND GUI_SRC set_source_files_properties( ${CMAKE_CURRENT_BINARY_DIR}/icons.c - ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.c - ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h - ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h - ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.c - ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.h - ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.shbin.h + ${CMAKE_CURRENT_BINARY_DIR}/uishader.c + ${CMAKE_CURRENT_BINARY_DIR}/uishader.h + ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin.h PROPERTIES GENERATED ON) add_executable(${BINARY_NAME}.elf ${GUI_SRC} main.c) @@ -68,36 +62,21 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icons.c DEPENDS ${CMAKE_SOURCE_DIR}/src/platform/3ds/icons.raw) add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h - MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/uishader.g.pica + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin.h + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/uishader.v.pica ${CMAKE_CURRENT_SOURCE_DIR}/uishader.g.pica COMMAND ${PICASSO} - -o ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin - -h ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin.h - ${CMAKE_CURRENT_SOURCE_DIR}/uishader.g.pica - COMMENT "picasso uishader.g.pica") - -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.h - MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin - COMMAND ${RAW2C} ${CMAKE_CURRENT_BINARY_DIR}/uishader_g.shbin - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "raw2c uishader.g.shbin") - -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.shbin ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.shbin.h - MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/uishader.v.pica - COMMAND ${PICASSO} - -o ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.shbin - -h ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.shbin.h + -o ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin + -h ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin.h ${CMAKE_CURRENT_SOURCE_DIR}/uishader.v.pica - COMMENT "picasso uishader.v.pica") + ${CMAKE_CURRENT_SOURCE_DIR}/uishader.g.pica + COMMENT "picasso uishader.shbin") add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.c ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.h - MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.shbin - COMMAND ${RAW2C} ${CMAKE_CURRENT_BINARY_DIR}/uishader_v.shbin + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/uishader.c ${CMAKE_CURRENT_BINARY_DIR}/uishader.h + MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin + COMMAND ${RAW2C} ${CMAKE_CURRENT_BINARY_DIR}/uishader.shbin WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "raw2c uishader.v.shbin") + COMMENT "raw2c uishader.shbin") add_custom_command(OUTPUT ${BINARY_NAME}.3dsx COMMAND ${3DSXTOOL} ${BINARY_NAME}.elf ${BINARY_NAME}.3dsx --smdh=${BINARY_NAME}.smdh diff --git a/src/platform/3ds/ctr-gpu.c b/src/platform/3ds/ctr-gpu.c index b7984b713..4123fa441 100644 --- a/src/platform/3ds/ctr-gpu.c +++ b/src/platform/3ds/ctr-gpu.c @@ -14,10 +14,8 @@ #include "ctr-gpu.h" -#include "uishader_v.h" -#include "uishader_v.shbin.h" -#include "uishader_g.h" -#include "uishader_g.shbin.h" +#include "uishader.h" +#include "uishader.shbin.h" struct ctrUIVertex { short x, y; @@ -25,6 +23,7 @@ struct ctrUIVertex { short u, v; short uw, vh; u32 abgr; + float rotate[2]; }; #define MAX_NUM_QUADS 256 @@ -36,34 +35,31 @@ static int ctrVertStart = 0; static C3D_Tex* activeTexture = NULL; -static shaderProgram_s gpuShader; -static DVLB_s* vertexShader = NULL; -static DVLB_s* geometryShader = NULL; +static shaderProgram_s uiProgram; +static DVLB_s* uiShader = NULL; +static int GSH_FVEC_projectionMtx; +static int GSH_FVEC_textureMtx; bool ctrInitGpu() { // Load vertex shader binary - vertexShader = DVLB_ParseFile((u32*) uishader_v, uishader_v_size); - if (vertexShader == NULL) { - return false; - } - - // Load geometry shader binary - geometryShader = DVLB_ParseFile((u32*) uishader_g, uishader_g_size); - if (geometryShader == NULL) { + uiShader = DVLB_ParseFile((u32*) uishader, uishader_size); + if (uiShader == NULL) { return false; } // Create shader - shaderProgramInit(&gpuShader); - Result res = shaderProgramSetVsh(&gpuShader, &vertexShader->DVLE[0]); + shaderProgramInit(&uiProgram); + Result res = shaderProgramSetVsh(&uiProgram, &uiShader->DVLE[0]); if (res < 0) { return false; } - res = shaderProgramSetGsh(&gpuShader, &geometryShader->DVLE[0], 3); + res = shaderProgramSetGsh(&uiProgram, &uiShader->DVLE[1], 4); if (res < 0) { return false; } - C3D_BindProgram(&gpuShader); + C3D_BindProgram(&uiProgram); + GSH_FVEC_projectionMtx = shaderInstanceGetUniformLocation(uiProgram.geometryShader, "projectionMtx"); + GSH_FVEC_textureMtx = shaderInstanceGetUniformLocation(uiProgram.geometryShader, "textureMtx"); // Allocate buffers ctrVertexBuffer = linearAlloc(VERTEX_BUFFER_SIZE); @@ -82,6 +78,7 @@ bool ctrInitGpu() { AttrInfo_AddLoader(attrInfo, 0, GPU_SHORT, 4); // in_pos AttrInfo_AddLoader(attrInfo, 1, GPU_SHORT, 4); // in_tc0 AttrInfo_AddLoader(attrInfo, 2, GPU_UNSIGNED_BYTE, 4); // in_col + AttrInfo_AddLoader(attrInfo, 3, GPU_FLOAT, 2); // in_rot return true; } @@ -92,23 +89,22 @@ void ctrDeinitGpu() { ctrVertexBuffer = NULL; } - shaderProgramFree(&gpuShader); + shaderProgramFree(&uiProgram); - if (vertexShader) { - DVLB_Free(vertexShader); - vertexShader = NULL; - } - - if (geometryShader) { - DVLB_Free(geometryShader); - geometryShader = NULL; + if (uiShader) { + DVLB_Free(uiShader); + uiShader = NULL; } } -void ctrSetViewportSize(s16 w, s16 h) { +void ctrSetViewportSize(s16 w, s16 h, bool tilt) { C3D_SetViewport(0, 0, h, w); C3D_Mtx projectionMtx; - Mtx_OrthoTilt(&projectionMtx, 0.0, w, h, 0.0, 0.0, 1.0); + if (tilt) { + Mtx_OrthoTilt(&projectionMtx, 0.0, w, h, 0.0, 0.0, 1.0, true); + } else { + Mtx_Ortho(&projectionMtx, 0.0, w, 0.0, h, 0.0, 1.0, true); + } C3D_FVUnifMtx4x4(GPU_GEOMETRY_SHADER, GSH_FVEC_projectionMtx, &projectionMtx); } @@ -145,7 +141,7 @@ void ctrActivateTexture(C3D_Tex* texture) { C3D_FVUnifMtx2x4(GPU_GEOMETRY_SHADER, GSH_FVEC_textureMtx, &textureMtx); } -void ctrAddRectScaled(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s16 vh) { +void ctrAddRectEx(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s16 vh, float rotate) { if (x >= 400 && w >= 0) { return; } @@ -170,12 +166,14 @@ void ctrAddRectScaled(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 u vtx->uw = uw; vtx->vh = vh; vtx->abgr = color; + vtx->rotate[0] = cosf(rotate); + vtx->rotate[1] = sinf(rotate); ++ctrNumVerts; } void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h) { - ctrAddRectScaled(color, x, y, w, h, u, v, w, h); + ctrAddRectEx(color, x, y, w, h, u, v, w, h, 0); } void ctrFlushBatch(void) { @@ -185,7 +183,7 @@ void ctrFlushBatch(void) { C3D_BufInfo* bufInfo = C3D_GetBufInfo(); BufInfo_Init(bufInfo); - BufInfo_Add(bufInfo, &ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex), 3, 0x210); + BufInfo_Add(bufInfo, &ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex), 4, 0x3210); GSPGPU_FlushDataCache(&ctrVertexBuffer[ctrVertStart], sizeof(struct ctrUIVertex) * ctrNumVerts); C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, ctrNumVerts); diff --git a/src/platform/3ds/ctr-gpu.h b/src/platform/3ds/ctr-gpu.h index 5f4cb6d3b..f97a23ba2 100644 --- a/src/platform/3ds/ctr-gpu.h +++ b/src/platform/3ds/ctr-gpu.h @@ -14,10 +14,10 @@ bool ctrInitGpu(void); void ctrDeinitGpu(void); -void ctrSetViewportSize(s16 w, s16 h); +void ctrSetViewportSize(s16 w, s16 h, bool tilt); void ctrActivateTexture(C3D_Tex* texture); -void ctrAddRectScaled(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s16 vh); +void ctrAddRectEx(u32 color, s16 x, s16 y, s16 w, s16 h, s16 u, s16 v, s16 uw, s16 vh, float rotate); void ctrAddRect(u32 color, s16 x, s16 y, s16 u, s16 v, s16 w, s16 h); void ctrFlushBatch(void); void ctrFinalize(void); diff --git a/src/platform/3ds/gui-font.c b/src/platform/3ds/gui-font.c index d3a27f864..2b79e730d 100644 --- a/src/platform/3ds/gui-font.c +++ b/src/platform/3ds/gui-font.c @@ -107,7 +107,9 @@ void GUIFontDrawGlyph(const struct GUIFont* font, int glyph_x, int glyph_y, uint u16 u = tex->width * data.texcoord.left; u16 v = tex->height * data.texcoord.bottom; - ctrAddRectScaled(color, x, y, tex->width * width * FONT_SIZE, tex->height * height * -FONT_SIZE, u, v, tex->width * width, tex->height * height); + ctrAddRectEx(color, x, y, + tex->width * width * FONT_SIZE, tex->height * height * -FONT_SIZE, + u, v, tex->width * width, tex->height * height, 0); } void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment align, enum GUIOrientation orient, uint32_t color, enum GUIIcon icon) { @@ -136,10 +138,16 @@ void GUIFontDrawIcon(const struct GUIFont* font, int x, int y, enum GUIAlignment } switch (orient) { case GUI_ORIENT_HMIRROR: - ctrAddRectScaled(color, x + metric.width, y, -metric.width, metric.height, metric.x, metric.y, metric.width, metric.height); + ctrAddRectEx(color, x + metric.width, y, + -metric.width, metric.height, + metric.x, metric.y, + metric.width, metric.height, 0); break; case GUI_ORIENT_VMIRROR: - ctrAddRectScaled(color, x, y + metric.height, metric.width, -metric.height, metric.x, metric.y, metric.width, metric.height); + ctrAddRectEx(color, x, y + metric.height, + metric.width, -metric.height, + metric.x, metric.y, + metric.width, metric.height, 0); break; case GUI_ORIENT_0: default: @@ -157,5 +165,9 @@ void GUIFontDrawIconSize(const struct GUIFont* font, int x, int y, int w, int h, } struct GUIIconMetric metric = defaultIconMetrics[icon]; - ctrAddRectScaled(color, x, y, w ? w : metric.width, h ? h : metric.height, metric.x, metric.y, metric.width, metric.height); + ctrAddRectEx(color, x, y, + w ? w : metric.width, + h ? h : metric.height, + metric.x, metric.y, + metric.width, metric.height, 0); } diff --git a/src/platform/3ds/main.c b/src/platform/3ds/main.c index d4121d6ba..a28e085b0 100644 --- a/src/platform/3ds/main.c +++ b/src/platform/3ds/main.c @@ -35,6 +35,13 @@ static enum ScreenMode { SM_MAX } screenMode = SM_PA_TOP; +static enum FilterMode { + FM_NEAREST, + FM_LINEAR_1x, + FM_LINEAR_2x, + FM_MAX +} filterMode = FM_LINEAR_2x; + #define _3DS_INPUT 0x3344534B #define AUDIO_SAMPLES 384 @@ -68,6 +75,7 @@ static bool frameLimiter = true; static C3D_RenderBuf bottomScreen; static C3D_RenderBuf topScreen; +static C3D_RenderBuf upscaleBuffer; static aptHookCookie cookie; @@ -78,7 +86,7 @@ static bool _initGpu(void) { return false; } - if (!C3D_RenderBufInit(&topScreen, 240, 400, GPU_RB_RGB8, 0) || !C3D_RenderBufInit(&bottomScreen, 240, 320, GPU_RB_RGB8, 0)) { + if (!C3D_RenderBufInit(&topScreen, 240, 400, GPU_RB_RGB8, 0) || !C3D_RenderBufInit(&bottomScreen, 240, 320, GPU_RB_RGB8, 0) || !C3D_RenderBufInit(&upscaleBuffer, 512, 512, GPU_RB_RGB565, 0)) { return false; } @@ -94,6 +102,7 @@ static void _cleanup(void) { C3D_RenderBufDelete(&topScreen); C3D_RenderBufDelete(&bottomScreen); + C3D_RenderBufDelete(&upscaleBuffer); C3D_Fini(); gfxExit(); @@ -210,7 +219,7 @@ static void _guiPrepare(void) { } C3D_RenderBufBind(&bottomScreen); - ctrSetViewportSize(320, 240); + ctrSetViewportSize(320, 240, true); } static void _guiFinish(void) { @@ -248,6 +257,14 @@ static void _setup(struct mGUIRunner* runner) { if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { screenMode = mode; } + if (mCoreConfigGetUIntValue(&runner->config, "filterMode", &mode) && mode < FM_MAX) { + filterMode = mode; + if (filterMode == FM_NEAREST) { + C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_NEAREST, GPU_NEAREST); + } else { + C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_LINEAR, GPU_LINEAR); + } + } frameLimiter = true; runner->core->setAudioBufferSize(runner->core, AUDIO_SAMPLES); @@ -292,9 +309,17 @@ static void _gameLoaded(struct mGUIRunner* runner) { memset(audioLeft, 0, AUDIO_SAMPLE_BUFFER * 2 * sizeof(int16_t)); } unsigned mode; - if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode != screenMode) { + if (mCoreConfigGetUIntValue(&runner->config, "screenMode", &mode) && mode < SM_MAX) { screenMode = mode; } + if (mCoreConfigGetUIntValue(&runner->config, "filterMode", &mode) && mode < FM_MAX) { + filterMode = mode; + if (filterMode == FM_NEAREST) { + C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_NEAREST, GPU_NEAREST); + } else { + C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_LINEAR, GPU_LINEAR); + } + } } static void _gameUnloaded(struct mGUIRunner* runner) { @@ -330,20 +355,27 @@ static void _gameUnloaded(struct mGUIRunner* runner) { } static void _drawTex(struct mCore* core, bool faded) { - if (screenMode < SM_PA_TOP) { + unsigned screen_w, screen_h; + switch (screenMode) { + case SM_PA_TOP: C3D_RenderBufBind(&bottomScreen); - ctrSetViewportSize(320, 240); - } else { + screen_w = 320; + screen_h = 240; + break; + case SM_PA_BOTTOM: C3D_RenderBufBind(&topScreen); - ctrSetViewportSize(400, 240); + screen_w = 400; + screen_h = 240; + break; + default: + C3D_RenderBufBind(&upscaleBuffer); + screen_w = upscaleBuffer.colorBuf.width; + screen_h = upscaleBuffer.colorBuf.height; + break; } - ctrActivateTexture(&outputTexture); u32 color = faded ? 0x3FFFFFFF : 0xFFFFFFFF; - int screen_w = screenMode < SM_PA_TOP ? 320 : 400; - int screen_h = 240; - unsigned corew, coreh; core->desiredVideoDimensions(core, &corew, &coreh); @@ -356,17 +388,57 @@ static void _drawTex(struct mCore* core, bool faded) { w = temp; } int gcd = h; - int aspectw = corew / gcd; - int aspecth = coreh / gcd; + unsigned aspectw = corew / gcd; + unsigned aspecth = coreh / gcd; + int x = 0; + int y = 0; switch (screenMode) { case SM_PA_TOP: case SM_PA_BOTTOM: - default: w = corew; h = coreh; + x = (screen_w - w) / 2; + y = (screen_h - h) / 2; + ctrSetViewportSize(screen_w, screen_h, true); + ctrActivateTexture(&outputTexture); break; case SM_AF_TOP: + case SM_AF_BOTTOM: + case SM_SF_TOP: + case SM_SF_BOTTOM: + default: + if (filterMode == FM_LINEAR_1x) { + w = corew; + h = coreh; + } else { + w = corew * 2; + h = coreh * 2; + } + ctrSetViewportSize(screen_w, screen_h, false); + ctrActivateTexture(&outputTexture); + break; + } + + ctrAddRectEx(color, x, y, w, h, 0, 0, corew, coreh, 0); + ctrFlushBatch(); + + corew = w; + coreh = h; + screen_h = 240; + if (screenMode < SM_PA_TOP) { + C3D_RenderBufBind(&bottomScreen); + screen_w = 320; + } else { + C3D_RenderBufBind(&topScreen); + screen_w = 400; + } + ctrSetViewportSize(screen_w, screen_h, true); + + switch (screenMode) { + default: + return; + case SM_AF_TOP: case SM_AF_BOTTOM: w = screen_w / aspectw; h = screen_h / aspecth; @@ -385,10 +457,10 @@ static void _drawTex(struct mCore* core, bool faded) { break; } - int x = (screen_w - w) / 2; - int y = (screen_h - h) / 2; - - ctrAddRectScaled(color, x, y, w, h, 0, 0, corew, coreh); + x = (screen_w - w) / 2; + y = (screen_h - h) / 2; + ctrActivateTexture(&upscaleBuffer.colorBuf); + ctrAddRectEx(color, x, y, w, h, 0, 0, corew, coreh, 0); ctrFlushBatch(); } @@ -604,7 +676,8 @@ int main() { return 1; } C3D_TexSetWrap(&outputTexture, GPU_CLAMP_TO_EDGE, GPU_CLAMP_TO_EDGE); - C3D_TexSetFilter(&outputTexture, GPU_LINEAR, GPU_LINEAR); + C3D_TexSetFilter(&outputTexture, GPU_NEAREST, GPU_NEAREST); + C3D_TexSetFilter(&upscaleBuffer.colorBuf, GPU_LINEAR, GPU_LINEAR); void* outputTextureEnd = (u8*)outputTexture.data + 256 * 256 * 2; // Zero texture data to make sure no garbage around the border interferes with filtering @@ -686,9 +759,21 @@ int main() { "Stretched/Top", }, .nStates = 6 + }, + { + .title = "Filtering", + .data = "filterMode", + .submenu = 0, + .state = FM_LINEAR_2x, + .validStates = (const char*[]) { + NULL, // Disable choosing nearest neighbor; it always looks bad + "Bilinear (smooter)", + "Bilinear (pixelated)", + }, + .nStates = 3 } }, - .nConfigExtra = 1, + .nConfigExtra = 2, .setup = _setup, .teardown = 0, .gameLoaded = _gameLoaded, diff --git a/src/platform/3ds/uishader.g.pica b/src/platform/3ds/uishader.g.pica index db14f6bf7..b5dadf546 100644 --- a/src/platform/3ds/uishader.g.pica +++ b/src/platform/3ds/uishader.g.pica @@ -5,6 +5,14 @@ ; License, v. 2.0. If a copy of the MPL was not distributed with this ; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; Inputs +.alias in_pos v0 ; [x, y, w, h] +.alias in_tc0 v1 ; [u, v, uw, vh] +.alias in_col v2 +.alias in_rot v3 + +.gsh point c0 + ; Uniforms .fvec projectionMtx[4] .fvec textureMtx[2] @@ -12,59 +20,77 @@ ; Constants .constf consts1(0.0, 1.0, -0.5, -1.0) -; Outputs : here only position and color +; Outputs .out out_pos position .out out_tc0 texcoord0 .out out_col color -; Inputs : here we have only vertices -.alias in_pos v0 -.alias in_tc0 v1 -.alias in_col v2 - -.gsh -.proc main +.entry gshMain +.proc gshMain ; Set up the vertex endpoints - mov r0.xy, in_pos.xy - mov r0.zw, consts1.zy - add r1.xy, r0.xy, in_pos.zw + mov r0.xy, in_pos.zw + mov r0.zw, consts1.xx + mov r4.xy, in_pos.xy + add r5, r4.xyzw, r0.xwww + add r6, r4.xyzw, r0.xyww + add r7, r4.xyzw, r0.wyww - dp4 r2.x, projectionMtx[0], r0 - dp4 r2.y, projectionMtx[1], r0 - dp4 r2.z, projectionMtx[2], r0 - dp4 r2.w, projectionMtx[3], r0 + ; Create rotation matrix + mov r8, in_rot.xzww + mov r9, in_rot.yxww + mov r10.zw, consts1.zy - dp4 r3.x, projectionMtx[0], r1 - dp4 r3.y, projectionMtx[1], r1 - dp4 r3.z, projectionMtx[2], r1 - dp4 r3.w, projectionMtx[3], r1 + ; Transform coordinates + dp4 r10.x, r8, r4 + dp4 r10.y, r9, r4 + dp4 r0.x, projectionMtx[0], r10 + dp4 r0.y, projectionMtx[1], r10 + dp4 r0.z, projectionMtx[2], r10 + dp4 r0.w, projectionMtx[3], r10 + + dp4 r10.x, r8, r5 + dp4 r10.y, r9, r5 + dp4 r1.x, projectionMtx[0], r10 + dp4 r1.y, projectionMtx[1], r10 + dp4 r1.z, projectionMtx[2], r10 + dp4 r1.w, projectionMtx[3], r10 + + dp4 r10.x, r8, r6 + dp4 r10.y, r9, r6 + dp4 r2.x, projectionMtx[0], r10 + dp4 r2.y, projectionMtx[1], r10 + dp4 r2.z, projectionMtx[2], r10 + dp4 r2.w, projectionMtx[3], r10 + + dp4 r10.x, r8, r7 + dp4 r10.y, r9, r7 + dp4 r3.x, projectionMtx[0], r10 + dp4 r3.y, projectionMtx[1], r10 + dp4 r3.z, projectionMtx[2], r10 + dp4 r3.w, projectionMtx[3], r10 ; Set up the texture endpoints - mov r0.xy, in_tc0.xy - mov r0.zw, consts1.xy - add r1.xy, r0.xy, in_tc0.zw + mov r6.xy, in_tc0.xy + add r7.xy, r6.xy, in_tc0.zw - dp4 r4.x, textureMtx[0], r0 - dp4 r4.y, textureMtx[1], r0 + dp4 r4.x, textureMtx[0], r6 + dp4 r4.y, textureMtx[1], r6 mov r4.zw, consts1.xy - dp4 r5.x, textureMtx[0], r1 - dp4 r5.y, textureMtx[1], r1 + dp4 r5.x, textureMtx[0], r7 + dp4 r5.y, textureMtx[1], r7 mov r5.zw, consts1.xy ; Emit top-left setemit 0 - mov out_pos.xyzw, r2.xyzw + mov out_pos, r0 mov out_tc0.xyzw, r4.xyzw mov out_col, in_col emit ; Emit bottom-left setemit 1 - mov out_pos.x, r2.x - mov out_pos.y, r3.y - mov out_pos.z, consts1.z - mov out_pos.w, consts1.y + mov out_pos, r1 mov out_tc0.x, r5.x mov out_tc0.y, r4.y mov out_tc0.z, consts1.x @@ -74,17 +100,14 @@ ; Emit bottom-right setemit 2, prim - mov out_pos.xyzw, r3.xyzw + mov out_pos, r2 mov out_tc0.xyzw, r5.xyzw mov out_col, in_col emit ; Emit top-right setemit 1, prim inv - mov out_pos.x, r3.x - mov out_pos.y, r2.y - mov out_pos.z, consts1.z - mov out_pos.w, consts1.y + mov out_pos, r3 mov out_tc0.x, r4.x mov out_tc0.y, r5.y mov out_tc0.z, consts1.x diff --git a/src/platform/3ds/uishader.v.pica b/src/platform/3ds/uishader.v.pica index ddb371502..4af474199 100644 --- a/src/platform/3ds/uishader.v.pica +++ b/src/platform/3ds/uishader.v.pica @@ -18,15 +18,19 @@ .out out_pos position .out out_tc0 texcoord0 .out out_col color +.out out_rot dummy ; Inputs .alias in_pos v0 .alias in_tc0 v1 .alias in_col v2 +.alias in_rot v3 -.proc main +.entry vshMain +.proc vshMain mov out_pos, in_pos mov out_tc0, in_tc0 + mul out_rot, consts1.ywyx, in_rot.xyy ; Normalize color by multiplying by 1 / 255 mul out_col, consts1.z, in_col