diff --git a/.clang-format b/.clang-format index 85393a2..bf8051d 100644 --- a/.clang-format +++ b/.clang-format @@ -4,6 +4,9 @@ AccessModifierOffset: -4 AlignAfterOpenBracket: DontAlign AllowShortBlocksOnASingleLine: true AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: AllIfsAndElse +AllowShortLoopsOnASingleLine: true BasedOnStyle: LLVM BraceWrapping: AfterClass: false diff --git a/d2gl/d2gl.vcxitems b/d2gl/d2gl.vcxitems index 55721aa..49e2072 100644 --- a/d2gl/d2gl.vcxitems +++ b/d2gl/d2gl.vcxitems @@ -26,6 +26,7 @@ + @@ -93,6 +94,7 @@ + @@ -122,6 +124,5 @@ - \ No newline at end of file diff --git a/d2gl/d2gl.vcxitems.filters b/d2gl/d2gl.vcxitems.filters index 1d57876..c75955d 100644 --- a/d2gl/d2gl.vcxitems.filters +++ b/d2gl/d2gl.vcxitems.filters @@ -31,6 +31,7 @@ + @@ -63,10 +64,10 @@ + - \ No newline at end of file diff --git a/d2gl/src/app.cpp b/d2gl/src/app.cpp index 331735e..badfd6e 100644 --- a/d2gl/src/app.cpp +++ b/d2gl/src/app.cpp @@ -64,8 +64,8 @@ void dllAttach(HMODULE hmodule) return; } - if (command_line.find("-log") != std::string::npos) - App.log = true; + App.log = command_line.find("-log") != std::string::npos; + App.direct = command_line.find("-direct") != std::string::npos; logInit(); trace_log("Renderer Api: %s", App.api == Api::Glide ? "Glide" : "DDraw"); diff --git a/d2gl/src/app.h b/d2gl/src/app.h index 2537cda..5c46f14 100644 --- a/d2gl/src/app.h +++ b/d2gl/src/app.h @@ -36,22 +36,22 @@ struct D2GLApp { bool log = false; bool video_test = false; bool ready = false; + bool direct = false; std::string menu_title = "D2GL"; - std::string version_str = "D2GL v1.2.2 by Bayaraa."; + std::string version_str = "1.3.0"; std::string ini_file = "d2gl.ini"; std::string mpq_file = "d2gl.mpq"; std::string log_file = "d2gl.log"; Api api = Api::Glide; std::unique_ptr context; - std::string gl_version = ""; + std::string gl_ver_str = ""; bool vsync = true; uint32_t frame_latency = 1; GLCaps gl_caps; - uint8_t gl_ver_major = 4; - uint8_t gl_ver_minor = 6; + glm::vec<2, uint8_t> gl_ver = { 4, 6 }; bool use_compute_shader = false; HMODULE hmodule = 0; @@ -86,7 +86,7 @@ struct D2GLApp { glm::uvec2 custom_size = { 0, 0 }; GameScreen screen = GameScreen::Movie; DrawStage draw_stage = DrawStage::World; - glm::uvec2 tex_size = { 0, 0 }; + glm::uvec2 tex_size = { 1024, 512 }; glm::vec2 tex_scale = { 1.0f, 1.0f }; } game; @@ -110,9 +110,18 @@ struct D2GLApp { Range range = { 25, 25, 60 }; } background_fps; - Select shader = {}; + struct { + Select presets = {}; + std::string preset = "bilinear.slangp"; + int selected = 0; + } shader; + Select lut = {}; - bool fxaa = false; + + struct { + bool active = false; + Select presets = { 1, { { "Low", 0 }, { "Medium", 1 }, { "High", 2 } } }; + } fxaa; struct { bool active = false; @@ -129,7 +138,7 @@ struct D2GLApp { struct { bool active = false; - Range scale = { 1.0f, 0.5f, 1.2f }; + Range scale = { 1.0f, 0.8f, 1.2f }; } hd_text; bool hd_cursor = false; @@ -137,6 +146,7 @@ struct D2GLApp { bool skip_intro = false; bool no_pickup = false; bool show_item_quantity = false; + bool show_monster_res = false; bool show_fps = false; struct { @@ -195,4 +205,13 @@ constexpr inline float FLOATVAL(float glide3x, float ddraw) #endif } +constexpr inline bool ISHDTEXT() +{ +#ifdef _HDTEXT + return true; +#else + return false; +#endif +} + } \ No newline at end of file diff --git a/d2gl/src/d2/common.cpp b/d2gl/src/d2/common.cpp index 8d8260d..246ba8f 100644 --- a/d2gl/src/d2/common.cpp +++ b/d2gl/src/d2/common.cpp @@ -189,8 +189,8 @@ void initHooks() unit_hover_patch.toggle(true); Patch show_item_quantity_patch = Patch(); - show_item_quantity_patch.add(PatchType::Auto, getOffset((DLL_D2CLIENT, 0x57566AFF), (0xB807D, 0x55536AFF), (0xBA42D, 0x55536AFF), (0x6B96B), (0x4689B), (0x9347B), (0x6B69B), (0x5F57B), (0x6EF78, 0x52536AFF)), 5, (uintptr_t)((isVerMax(V_110) || isVer(V_114d)) ? drawItemImageBeginPatchESI : drawItemImageBeginPatch)); - show_item_quantity_patch.add(PatchType::Auto, getOffset((DLL_D2CLIENT, 0xD1E803C5), (0xB80B8, 0xBAFF0000), (0xBA468, 0xBAFF0000), (0x6B993), (0x468C3), (0x934A3), (0x6B6C3), (0x5F5A3), (0x6EF9D, 0xD1E803C7)), 5, (uintptr_t)drawItemImageEndPatch); + show_item_quantity_patch.add(PatchType::Auto, getOffset((DLL_D2CLIENT, 0x8A442416), (0x3AD84, 0x558BD38B), (0x410ED, 0x8B6C241C), (0xAF14E), (0x7A1BE), (0xAF88E), (0x95A2E), (0x99DFE), (0x841A1, 0x8A4DFF8A)), isVer(V_109d) ? 5 : 6, (uintptr_t)(isVerMax(V_110) ? drawInvItemPatchESI : (isVer(V_114d) ? drawInvItemPatchEDI : drawInvItemPatch))); + show_item_quantity_patch.add(PatchType::Auto, getOffset((DLL_D2CLIENT, 0x8A442416), (0x3AF2D, 0x558BD38B), (0x4128F, 0x8B6C241C), (0xAF26D), (0x7A2DD), (0xAF9AD), (0x95B4D), (0x99F1D), (0x842BF, 0x8A4DFF8A)), isVer(V_109d) ? 5 : 6, (uintptr_t)(isVerMax(V_110) ? drawInvItemPatchESI : (isVer(V_114d) ? drawInvItemPatchEDI : drawInvItemPatch))); show_item_quantity_patch.toggle(true); patch_motion_prediction = std::make_unique(); diff --git a/d2gl/src/d2/funcs.cpp b/d2gl/src/d2/funcs.cpp index 03959e7..f066283 100644 --- a/d2gl/src/d2/funcs.cpp +++ b/d2gl/src/d2/funcs.cpp @@ -228,7 +228,7 @@ void __stdcall drawImageHooked(CellContext* cell, int x, int y, uint32_t gamma, drawImage(cell, pos.x, pos.y, gamma, draw_mode, palette); } - modules::HDText::drawItemQuantity(x, y); + modules::HDText::drawItemQuantity(true); } void __stdcall drawPerspectiveImageHooked(CellContext* cell, int x, int y, uint32_t gamma, int draw_mode, int screen_mode, uint8_t* palette) @@ -279,6 +279,8 @@ void __stdcall drawSolidRectExHooked(int left, int top, int right, int bottom, u auto offset = modules::MotionPrediction::Instance().drawSolidRect(); if (!modules::HDText::Instance().drawSolidRect(left - offset.x, top - offset.y, right - offset.x, bottom - offset.y, color, draw_mode)) drawSolidRectEx(left - offset.x, top - offset.y, right - offset.x, bottom - offset.y, color, draw_mode); + + modules::HDText::drawItemQuantity(false, left, bottom); } void __stdcall drawLineHooked(int x_start, int y_start, int x_end, int y_end, uint8_t color, uint8_t alpha) diff --git a/d2gl/src/d2/structs.h b/d2gl/src/d2/structs.h index 3e2f505..c8f24f6 100644 --- a/d2gl/src/d2/structs.h +++ b/d2gl/src/d2/structs.h @@ -45,6 +45,16 @@ namespace d2gl::d2 { #define SCREENPANEL_LEFT 2 #define SCREENPANEL_BOTH 3 +#define STAT_HP 6 +#define STAT_MAXHP 7 +#define STAT_DMGREDUCTIONPCT 36 +#define STAT_MAGICDMGREDUCTIONPCT 37 +#define STAT_FIRERESIST 39 +#define STAT_LIGHTNINGRESIST 41 +#define STAT_COLDRESIST 43 +#define STAT_POISONRESIST 45 +#define STAT_ITEMQUANTITY 70 + enum class UnitType { Player, Monster, diff --git a/d2gl/src/d2/stubs.cpp b/d2gl/src/d2/stubs.cpp index 5929621..5d35822 100644 --- a/d2gl/src/d2/stubs.cpp +++ b/d2gl/src/d2/stubs.cpp @@ -471,7 +471,7 @@ __declspec(naked) void unitHoverEndPatch() } } -__declspec(naked) void drawItemImageBeginPatch() +__declspec(naked) void drawInvItemPatch() { __asm { @@ -480,20 +480,20 @@ __declspec(naked) void drawItemImageBeginPatch() } } -__declspec(naked) void drawItemImageBeginPatchESI() +__declspec(naked) void drawInvItemPatchEDI() { __asm { - mov currently_drawing_item, esi + mov currently_drawing_item, edi ret } } -__declspec(naked) void drawItemImageEndPatch() +__declspec(naked) void drawInvItemPatchESI() { __asm { - mov currently_drawing_item, 0x0 + mov currently_drawing_item, esi ret } } diff --git a/d2gl/src/d2/stubs.h b/d2gl/src/d2/stubs.h index ac5691c..5a06ced 100644 --- a/d2gl/src/d2/stubs.h +++ b/d2gl/src/d2/stubs.h @@ -53,9 +53,9 @@ void unitHoverBeginPatch(); void unitHoverMidPatch(); void unitHoverEndPatch(); -void drawItemImageBeginPatch(); -void drawItemImageBeginPatchESI(); -void drawItemImageEndPatch(); +void drawInvItemPatch(); +void drawInvItemPatchEDI(); +void drawInvItemPatchESI(); void loadUIImageStub(); void loadUIImageStubECX(); diff --git a/d2gl/src/graphic/command_buffer.cpp b/d2gl/src/graphic/command_buffer.cpp index 1531835..ce53e23 100644 --- a/d2gl/src/graphic/command_buffer.cpp +++ b/d2gl/src/graphic/command_buffer.cpp @@ -59,6 +59,7 @@ void CommandBuffer::resize() m_resized = true; m_game_size = App.game.size; m_game_tex_bpp = App.game.bpp; + m_window_size = App.window.size; } void CommandBuffer::colorUpdate(UBOType type, const void* data) diff --git a/d2gl/src/graphic/context.cpp b/d2gl/src/graphic/context.cpp index 34e0854..79641b7 100644 --- a/d2gl/src/graphic/context.cpp +++ b/d2gl/src/graphic/context.cpp @@ -25,6 +25,7 @@ #include "modules/mini_map.h" #include "modules/motion_prediction.h" #include "option/menu.h" +#include "upscaler.h" #include "win32.h" #include @@ -61,9 +62,9 @@ Context::Context() std::vector> versions = { { 4, 6 }, { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 }, { 3, 3 } }; for (auto& version : versions) { - if (App.gl_ver_major < version.x) + if (App.gl_ver.x < version.x) continue; - if (App.gl_ver_minor < version.y) + if (App.gl_ver.y < version.y) continue; int attribs[] = { @@ -75,8 +76,10 @@ Context::Context() if (App.debug) attribs[5] |= WGL_CONTEXT_DEBUG_BIT_ARB; - if (m_context = wglCreateContextAttribsARB(App.hdc, 0, attribs)) + if (m_context = wglCreateContextAttribsARB(App.hdc, 0, attribs)) { + App.gl_ver = version; break; + } } if (!m_context) { @@ -96,7 +99,7 @@ Context::Context() sprintf_s(version_str, "%d.%d", major_version, minor_version); trace_log("OpenGL: %s (%s | %s)", version_str, glGetString(GL_RENDERER), glGetString(GL_VENDOR)); trace_log("OpenGL: Shading Language: %s", version_str, glGetString(GL_SHADING_LANGUAGE_VERSION)); - App.gl_version = version_str; + App.gl_ver_str = version_str; GLint max_texture_unit; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_unit); @@ -124,6 +127,7 @@ Context::Context() glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); + glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); uint32_t offset = 0; @@ -158,15 +162,11 @@ Context::Context() imguiInit(); - PipelineCreateInfo movie_pipeline_ci; + PipelineCreateInfo movie_pipeline_ci = { "movie" }; movie_pipeline_ci.shader = g_shader_movie; - movie_pipeline_ci.bindings = { { BindingType::Texture, "u_Texture", TEXTURE_SLOT_DEFAULT } }; + movie_pipeline_ci.bindings = { { BindingType::Texture, "u_Texture", TEXTURE_SLOT_DEFAULT, &m_game_texture } }; m_movie_pipeline = Context::createPipeline(movie_pipeline_ci); - UniformBufferCreateInfo upscale_ubo_ci; - upscale_ubo_ci.variables = { { "out_size", sizeof(glm::vec2) }, { "tex_size", sizeof(glm::vec2) }, { "rel_size", sizeof(glm::vec2) } }; - m_upscale_ubo = Context::createUniformBuffer(upscale_ubo_ci); - UniformBufferCreateInfo postfx_ubo_ci; postfx_ubo_ci.variables = { { "sharpen", sizeof(glm::vec4) }, { "rel_size", sizeof(glm::vec2) } }; m_postfx_ubo = Context::createUniformBuffer(postfx_ubo_ci); @@ -174,61 +174,65 @@ Context::Context() m_sharpen_data = { App.sharpen.strength.value, App.sharpen.clamp.value, App.sharpen.radius.value }; m_postfx_ubo->updateDataVec4f("sharpen", glm::vec4(m_sharpen_data, 1.0f)); - PipelineCreateInfo postfx_pipeline_ci; + PipelineCreateInfo postfx_pipeline_ci = { "postfx" }; postfx_pipeline_ci.shader = g_shader_postfx; postfx_pipeline_ci.bindings = { { BindingType::UniformBuffer, "ubo_Metrics", m_postfx_ubo->getBinding() }, - { BindingType::Texture, "u_Texture0", TEXTURE_SLOT_POSTFX1 }, - { BindingType::Texture, "u_Texture1", TEXTURE_SLOT_POSTFX2 }, + { BindingType::FBTexture, "u_Texture0", TEXTURE_SLOT_POSTFX1, &m_postfx_framebuffer }, + { BindingType::Texture, "u_Texture1", TEXTURE_SLOT_POSTFX2, &m_postfx_texture }, }; m_postfx_pipeline = Context::createPipeline(postfx_pipeline_ci); m_postfx_pipeline->setUniformMat4f("u_MVP", glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f)); if (App.gl_caps.compute_shader) { - PipelineCreateInfo fxaa_pipeline_ci; + PipelineCreateInfo fxaa_pipeline_ci = { "compute fxaa" }; fxaa_pipeline_ci.shader = g_shader_postfx; + fxaa_pipeline_ci.version = { 4, 3 }; fxaa_pipeline_ci.bindings = { - { BindingType::Texture, "u_InTexture", TEXTURE_SLOT_POSTFX2 }, + { BindingType::Texture, "u_InTexture", TEXTURE_SLOT_POSTFX2, &m_postfx_texture }, { BindingType::Image, "u_OutTexture", IMAGE_UNIT_FXAA }, }; fxaa_pipeline_ci.compute = true; m_fxaa_compute_pipeline = Context::createPipeline(fxaa_pipeline_ci); } - PipelineCreateInfo mod_pipeline_ci; + PipelineCreateInfo mod_pipeline_ci = { "module" }; mod_pipeline_ci.shader = g_shader_mod; mod_pipeline_ci.attachment_blends = { { BlendType::SAlpha_OneMinusSAlpha } }; mod_pipeline_ci.bindings = { - { BindingType::Texture, "u_MapTexture", TEXTURE_SLOT_MAP }, { BindingType::Texture, "u_CursorTexture", TEXTURE_SLOT_CURSOR }, { BindingType::Texture, "u_FontTexture", TEXTURE_SLOT_FONTS }, - { BindingType::Texture, "u_MaskTexture", TEXTURE_SLOT_MASK }, }; + if (ISGLIDE3X()) { + mod_pipeline_ci.bindings.push_back({ BindingType::FBTexture, "u_MapTexture", TEXTURE_SLOT_MAP, &m_game_framebuffer, 1 }); + mod_pipeline_ci.bindings.push_back({ BindingType::FBTexture, "u_MaskTexture", TEXTURE_SLOT_MASK, &m_game_framebuffer, 2 }); + } m_mod_pipeline = Context::createPipeline(mod_pipeline_ci); + m_mod_pipeline->setUniform1i("u_IsGlide", ISGLIDE3X()); if (ISGLIDE3X()) { TextureCreateInfo glide_texture_ci; glide_texture_ci.size = { 512, 512 }; glide_texture_ci.layer_count = 512; - glide_texture_ci.format = GL_RED; + glide_texture_ci.format = { GL_R8, GL_RED }; m_glide_texture = std::make_unique(glide_texture_ci); TextureCreateInfo movie_texture_ci; movie_texture_ci.size = { 640, 480 }; - movie_texture_ci.min_filter = GL_LINEAR; - movie_texture_ci.mag_filter = GL_LINEAR; - movie_texture_ci.format = GL_BGRA; + movie_texture_ci.filter = { GL_LINEAR, GL_LINEAR }; + movie_texture_ci.format = { GL_RGBA8, GL_BGRA }; m_game_texture = Context::createTexture(movie_texture_ci); UniformBufferCreateInfo game_ubo_ci; game_ubo_ci.variables = { { "palette", 256 * sizeof(glm::vec4) }, { "gamma", 256 * sizeof(glm::vec4) } }; m_game_color_ubo = Context::createUniformBuffer(game_ubo_ci); - PipelineCreateInfo game_pipeline_ci; + PipelineCreateInfo game_pipeline_ci = { "glide" }; + game_pipeline_ci.version = { 3, 3 }; game_pipeline_ci.shader = g_shader_glide; game_pipeline_ci.bindings = { { BindingType::UniformBuffer, "ubo_Colors", m_game_color_ubo->getBinding() }, - { BindingType::Texture, "u_Texture", TEXTURE_SLOT_DEFAULT }, + { BindingType::Texture, "u_Texture", TEXTURE_SLOT_DEFAULT, &m_glide_texture }, }; game_pipeline_ci.attachment_blends.clear(); for (auto& blend : g_blend_types) @@ -246,10 +250,11 @@ Context::Context() helpers::clearImage(image_data); if (App.gl_caps.compute_shader) { - PipelineCreateInfo blur_pipeline_ci; + PipelineCreateInfo blur_pipeline_ci = { "compute blur" }; blur_pipeline_ci.shader = g_shader_prefx; + blur_pipeline_ci.version = { 4, 3 }; blur_pipeline_ci.bindings = { - { BindingType::Texture, "u_InTexture", TEXTURE_SLOT_BLOOM2 }, + { BindingType::Texture, "u_InTexture", TEXTURE_SLOT_BLOOM2, &m_bloom_texture }, { BindingType::Image, "u_OutTexture", IMAGE_UNIT_BLUR }, }; blur_pipeline_ci.compute = true; @@ -263,14 +268,14 @@ Context::Context() m_bloom_data = { App.bloom.exposure.value, App.bloom.gamma.value }; m_bloom_ubo->updateDataVec2f("bloom", m_bloom_data); - PipelineCreateInfo prefx_pipeline_ci; + PipelineCreateInfo prefx_pipeline_ci = { "prefx" }; prefx_pipeline_ci.shader = g_shader_prefx; prefx_pipeline_ci.bindings = { { BindingType::UniformBuffer, "ubo_Metrics", m_bloom_ubo->getBinding() }, - { BindingType::Texture, "u_Texture", TEXTURE_SLOT_PREFX }, - { BindingType::Texture, "u_BloomTexture1", TEXTURE_SLOT_BLOOM1 }, - { BindingType::Texture, "u_BloomTexture2", TEXTURE_SLOT_BLOOM2 }, - { BindingType::Texture, "u_LUTTexture", m_lut_texture->getSlot() }, + { BindingType::Texture, "u_Texture", TEXTURE_SLOT_PREFX, &m_prefx_texture }, + { BindingType::FBTexture, "u_BloomTexture1", TEXTURE_SLOT_BLOOM1, &m_bloom_framebuffer }, + { BindingType::Texture, "u_BloomTexture2", TEXTURE_SLOT_BLOOM2, &m_bloom_texture }, + { BindingType::Texture, "u_LUTTexture", m_lut_texture->getSlot(), &m_lut_texture }, }; m_prefx_pipeline = Context::createPipeline(prefx_pipeline_ci); m_prefx_pipeline->setUniformMat4f("u_MVP", glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f)); @@ -279,11 +284,11 @@ Context::Context() ubo_ci.variables = { { "palette", 256 * sizeof(glm::vec4) } }; m_game_color_ubo = Context::createUniformBuffer(ubo_ci); - PipelineCreateInfo game_pipeline_ci; + PipelineCreateInfo game_pipeline_ci = { "ddraw" }; game_pipeline_ci.shader = g_shader_ddraw; game_pipeline_ci.bindings = { { BindingType::UniformBuffer, "ubo_Colors", m_game_color_ubo->getBinding() }, - { BindingType::Texture, "u_Texture", TEXTURE_SLOT_DEFAULT }, + { BindingType::Texture, "u_Texture", TEXTURE_SLOT_DEFAULT, &m_game_texture }, }; m_game_pipeline = Context::createPipeline(game_pipeline_ci); m_game_pipeline->setUniformMat4f("u_MVP", glm::ortho(-1.0f, 1.0f, 1.0f, -1.0f)); @@ -355,6 +360,9 @@ void Context::renderThread(void* context) if (cmd->m_resized) ctx->onResize(cmd->m_window_size, cmd->m_game_size, cmd->m_game_tex_bpp); + if (ctx->m_current_shader != App.shader.selected) + ctx->onShaderChange(); + if (cmd->m_vertex_count) glBufferSubData(GL_ARRAY_BUFFER, 0, cmd->m_vertex_count * sizeof(Vertex), ctx->m_vertices.data[frame_index].data()); @@ -376,6 +384,8 @@ void Context::renderThread(void* context) } Vertex::bindingDescription(); + const glm::ivec2 vp_size = { App.viewport.stretched.x ? App.window.size.x : App.viewport.size.x, App.viewport.stretched.y ? App.window.size.y : App.viewport.size.y }; + const glm::ivec2 vp_offset = { App.viewport.stretched.x ? 0 : App.viewport.offset.x, App.viewport.stretched.y ? 0 : App.viewport.offset.y }; for (uint32_t i = 0; i < cmd->m_count; i++) { const auto command = &cmd->m_commands[i]; @@ -393,6 +403,7 @@ void Context::renderThread(void* context) glDrawElementsBaseVertex(GL_TRIANGLES, command->draw.count, GL_UNSIGNED_INT, 0, command->draw.start); break; case CommandType::PreFx: + ctx->m_prefx_texture->fillFromBuffer(ctx->m_game_framebuffer); ctx->bindPipeline(ctx->m_prefx_pipeline); @@ -425,7 +436,7 @@ void Context::renderThread(void* context) ctx->setViewport(cmd->m_game_size); ctx->bindPipeline(ctx->m_prefx_pipeline); } - ctx->drawQuad(3 + App.bloom.active, { App.lut.selected, 0 }); + ctx->drawQuad(3 + App.bloom.active, 0, App.lut.selected); ctx->bindPipeline(ctx->m_game_pipeline, command->index); break; @@ -443,9 +454,6 @@ void Context::renderThread(void* context) ctx->bindPipeline(ctx->m_movie_pipeline); ctx->drawQuad(); } else { - if (ctx->m_current_shader != App.shader.selected) - ctx->onShaderChange(); - if (App.sharpen.active) { const auto sharpen_data = glm::vec3(App.sharpen.strength.value, App.sharpen.clamp.value, App.sharpen.radius.value); if (ctx->m_sharpen_data != sharpen_data) { @@ -467,41 +475,31 @@ void Context::renderThread(void* context) ctx->drawQuad(); } - ctx->m_upscale_texture->fillFromBuffer(ctx->m_game_framebuffer); - - const glm::ivec2 viewport_size = { App.viewport.stretched.x ? App.window.size.x : App.viewport.size.x, App.viewport.stretched.y ? App.window.size.y : App.viewport.size.y }; - const glm::ivec2 viewport_offset = { App.viewport.stretched.x ? 0 : App.viewport.offset.x, App.viewport.stretched.y ? 0 : App.viewport.offset.y }; - - if (App.sharpen.active || App.fxaa) { - ctx->bindFrameBuffer(ctx->m_postfx_framebuffer, false); - ctx->setViewport(App.viewport.size); - } else { - ctx->bindDefaultFrameBuffer(); - ctx->setViewport(viewport_size, viewport_offset); - } - ctx->bindPipeline(ctx->m_upscale_pipeline); - ctx->drawQuad(); + if (App.sharpen.active || App.fxaa.active) + Upscaler::Instance().process(ctx->m_game_framebuffer, vp_size, vp_offset, ctx->m_postfx_framebuffer); + else + Upscaler::Instance().process(ctx->m_game_framebuffer, vp_size, vp_offset); if (App.sharpen.active) { - if (App.fxaa) + if (App.fxaa.active) ctx->m_postfx_texture->fillFromBuffer(ctx->m_postfx_framebuffer); else { ctx->bindDefaultFrameBuffer(); - ctx->setViewport(viewport_size, viewport_offset); + ctx->setViewport(vp_size, vp_offset); } ctx->bindPipeline(ctx->m_postfx_pipeline); - ctx->drawQuad(App.fxaa); + ctx->drawQuad(App.fxaa.active); } - if (App.fxaa) { + if (App.fxaa.active) { if (App.gl_caps.compute_shader) { ctx->m_postfx_texture->fillFromBuffer(ctx->m_postfx_framebuffer); - ctx->m_fxaa_compute_pipeline->dispatchCompute(0, ctx->m_fxaa_work_size, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + ctx->m_fxaa_compute_pipeline->dispatchCompute(App.fxaa.presets.selected, ctx->m_fxaa_work_size, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); } ctx->bindDefaultFrameBuffer(); - ctx->setViewport(viewport_size, viewport_offset); + ctx->setViewport(vp_size, vp_offset); ctx->bindPipeline(ctx->m_postfx_pipeline); - ctx->drawQuad(2 + App.gl_caps.compute_shader); + ctx->drawQuad(2 + App.gl_caps.compute_shader, App.fxaa.presets.selected); } } break; @@ -520,6 +518,7 @@ void Context::renderThread(void* context) ctx->m_mod_pipeline->setUniform1i("u_IsMasking", cmd->m_hd_text_mask.masking); cmd->m_hd_text_mask.active = false; } + VertexMod::bindingDescription(); glDrawElements(GL_TRIANGLES, cmd->m_vertex_mod_count / 4 * 6, GL_UNSIGNED_INT, 0); } @@ -564,16 +563,13 @@ void Context::onResize(glm::uvec2 w_size, glm::uvec2 g_size, uint32_t bpp) modules::HDText::Instance().setMVP(mvp); m_mod_pipeline->setUniformMat4f("u_MVP", mvp); - m_upscale_ubo->updateDataVec2f("tex_size", { (float)App.game.tex_size.x, (float)App.game.tex_size.y }); - m_upscale_ubo->updateDataVec2f("rel_size", { 1.0f / App.game.tex_size.x, 1.0f / App.game.tex_size.y }); - FrameBufferCreateInfo frambuffer_ci; frambuffer_ci.size = game_size; if (ISGLIDE3X()) frambuffer_ci.attachments = { - { TEXTURE_SLOT_GAME, { 0.0f, 0.0f, 0.0f, 1.0f }, GL_LINEAR, GL_LINEAR }, + { TEXTURE_SLOT_GAME, { 0.0f, 0.0f, 0.0f, 1.0f }, { GL_LINEAR, GL_LINEAR } }, { TEXTURE_SLOT_MAP, { 0.0f, 0.0f, 0.0f, 0.0f } }, - { TEXTURE_SLOT_MASK, { 0.0f, 0.0f, 0.0f, 0.0f }, GL_LINEAR, GL_LINEAR, GL_RED }, + { TEXTURE_SLOT_MASK, { 0.0f, 0.0f, 0.0f, 0.0f }, { GL_LINEAR, GL_LINEAR }, { GL_R8, GL_RED } }, }; else frambuffer_ci.attachments = { { TEXTURE_SLOT_GAME } }; @@ -588,7 +584,7 @@ void Context::onResize(glm::uvec2 w_size, glm::uvec2 g_size, uint32_t bpp) FrameBufferCreateInfo bloom_frambuffer_ci; bloom_frambuffer_ci.size = m_bloom_tex_size; - bloom_frambuffer_ci.attachments = { { TEXTURE_SLOT_BLOOM1, {}, GL_LINEAR, GL_LINEAR }, { TEXTURE_SLOT_BLOOM2 } }; + bloom_frambuffer_ci.attachments = { { TEXTURE_SLOT_BLOOM1, {}, { GL_LINEAR, GL_LINEAR } } }; m_bloom_framebuffer = Context::createFrameBuffer(bloom_frambuffer_ci); if (App.gl_caps.compute_shader) m_bloom_framebuffer->getTexture()->bindImage(IMAGE_UNIT_BLUR); @@ -596,8 +592,7 @@ void Context::onResize(glm::uvec2 w_size, glm::uvec2 g_size, uint32_t bpp) TextureCreateInfo bloom_texture_ci; bloom_texture_ci.size = m_bloom_tex_size; bloom_texture_ci.slot = TEXTURE_SLOT_BLOOM2; - bloom_texture_ci.min_filter = GL_LINEAR; - bloom_texture_ci.mag_filter = GL_LINEAR; + bloom_texture_ci.filter = { GL_LINEAR, GL_LINEAR }; m_bloom_texture = Context::createTexture(bloom_texture_ci); TextureCreateInfo prefx_texture_ci; @@ -607,9 +602,11 @@ void Context::onResize(glm::uvec2 w_size, glm::uvec2 g_size, uint32_t bpp) } else { TextureCreateInfo texture_ci; texture_ci.size = game_size; - texture_ci.format = color_bpp == 8 ? GL_RED : GL_BGRA; - texture_ci.min_filter = GL_LINEAR; - texture_ci.mag_filter = GL_LINEAR; + if (color_bpp == 8) + texture_ci.format = { GL_R8, GL_RED }; + else + texture_ci.format = { GL_RGBA8, GL_BGRA }; + texture_ci.filter = { GL_LINEAR, GL_LINEAR }; m_game_texture = Context::createTexture(texture_ci); } } @@ -621,58 +618,44 @@ void Context::onResize(glm::uvec2 w_size, glm::uvec2 g_size, uint32_t bpp) m_movie_pipeline->setUniformMat4f("u_MVP", glm::ortho(-1.0f * offset_x, 1.0f * offset_x, 1.0f * offset_y, -1.0f * offset_y)); } - FrameBufferCreateInfo frambuffer_ci; - frambuffer_ci.size = App.viewport.size; - frambuffer_ci.attachments = { { TEXTURE_SLOT_POSTFX1, {}, GL_LINEAR, GL_LINEAR } }; - m_postfx_framebuffer = Context::createFrameBuffer(frambuffer_ci); - if (App.gl_caps.compute_shader) - m_postfx_framebuffer->getTexture()->bindImage(IMAGE_UNIT_FXAA); + if (game_resized || window_resized) { + FrameBufferCreateInfo frambuffer_ci; + frambuffer_ci.size = App.viewport.size; + frambuffer_ci.attachments = { { TEXTURE_SLOT_POSTFX1, {}, { GL_LINEAR, GL_LINEAR } } }; + m_postfx_framebuffer = Context::createFrameBuffer(frambuffer_ci); + if (App.gl_caps.compute_shader) + m_postfx_framebuffer->getTexture()->bindImage(IMAGE_UNIT_FXAA); - m_fxaa_work_size = { ceil((float)App.viewport.size.x / 16), ceil((float)App.viewport.size.y / 16) }; + m_fxaa_work_size = { ceil((float)App.viewport.size.x / 16), ceil((float)App.viewport.size.y / 16) }; - TextureCreateInfo texture_ci; - texture_ci.size = App.viewport.size; - texture_ci.slot = TEXTURE_SLOT_POSTFX2; - texture_ci.min_filter = GL_LINEAR; - texture_ci.mag_filter = GL_LINEAR; - m_postfx_texture = Context::createTexture(texture_ci); + TextureCreateInfo texture_ci; + texture_ci.size = App.viewport.size; + texture_ci.slot = TEXTURE_SLOT_POSTFX2; + texture_ci.filter = { GL_LINEAR, GL_LINEAR }; + m_postfx_texture = Context::createTexture(texture_ci); + + onShaderChange(); + } - onShaderChange(game_resized); - m_upscale_ubo->updateDataVec2f("out_size", { (float)App.game.tex_size.x * App.viewport.scale.x, (float)App.game.tex_size.y * App.viewport.scale.y }); m_postfx_ubo->updateDataVec2f("rel_size", { 1.0f / App.viewport.size.x, 1.0f / App.viewport.size.y }); m_mod_pipeline->setUniformVec2f("u_Scale", App.viewport.scale); - m_mod_pipeline->setUniformVec4f("u_Viewport", { (float)App.viewport.offset.x, (float)App.viewport.offset.y, (float)App.viewport.size.x, (float)App.viewport.size.y }); + + const glm::ivec2 vp_size = { App.viewport.stretched.x ? App.window.size.x : App.viewport.size.x, App.viewport.stretched.y ? App.window.size.y : App.viewport.size.y }; + const glm::ivec2 vp_offset = { App.viewport.stretched.x ? 0 : App.viewport.offset.x, App.viewport.stretched.y ? 0 : App.viewport.offset.y }; + m_mod_pipeline->setUniformVec4f("u_Viewport", { (float)vp_offset.x, (float)vp_offset.y, (float)vp_size.x, (float)vp_size.y }); modules::MiniMap::Instance().resize(); toggleVsync(); } -void Context::onShaderChange(bool texture) +void Context::onShaderChange() { - const auto shader = g_shader_upscale[App.shader.selected]; - - if (texture || m_current_shader != App.shader.selected) { - TextureCreateInfo texture_ci; - texture_ci.size = App.game.tex_size; - texture_ci.slot = TEXTURE_SLOT_UPSCALE; - if (shader.linear) { - texture_ci.min_filter = GL_LINEAR; - texture_ci.mag_filter = GL_LINEAR; - } - m_upscale_texture = Context::createTexture(texture_ci); - } - if (m_current_shader != App.shader.selected) { - PipelineCreateInfo pipeline_ci; - pipeline_ci.shader = shader.source; - pipeline_ci.bindings = { - { BindingType::UniformBuffer, "ubo_Metrics", m_upscale_ubo->getBinding() }, - { BindingType::Texture, "u_Texture", TEXTURE_SLOT_UPSCALE }, - }; - m_upscale_pipeline = Context::createPipeline(pipeline_ci); + if (!Upscaler::Instance().loadPreset()) + Upscaler::Instance().loadDefaultPreset(); } - m_upscale_pipeline->setUniformMat4f("u_MVP", glm::ortho(-App.game.tex_scale.x, App.game.tex_scale.x, -App.game.tex_scale.y, App.game.tex_scale.y)); + Upscaler::Instance().setupPasses(); m_current_shader = App.shader.selected; } @@ -845,7 +828,7 @@ void Context::flushVertices() m_frame.drawcall_count++; } -void Context::drawQuad(int8_t flag_x, glm::vec<2, int16_t> tex_ids) +void Context::drawQuad(int8_t flag_x, int8_t flag_y, int16_t tex_id) { static Vertex quad[4] = { { { glm::detail::toFloat16(-1.0f), glm::detail::toFloat16(-1.0f) }, { 0.0f, 0.0f } }, @@ -854,8 +837,8 @@ void Context::drawQuad(int8_t flag_x, glm::vec<2, int16_t> tex_ids) { { glm::detail::toFloat16(-1.0f), glm::detail::toFloat16(+1.0f) }, { 0.0f, 1.0f } }, }; for (size_t i = 0; i < 4; i++) { - quad[i].tex_ids = tex_ids; - quad[i].flags = { flag_x, 0, 0, 0 }; + quad[i].tex_ids = { tex_id, 0 }; + quad[i].flags = { flag_x, flag_y, 0, 0 }; } glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(quad), &quad[0]); diff --git a/d2gl/src/graphic/context.h b/d2gl/src/graphic/context.h index b63972a..fb736f8 100644 --- a/d2gl/src/graphic/context.h +++ b/d2gl/src/graphic/context.h @@ -39,18 +39,17 @@ namespace d2gl { #define TEXTURE_SLOT_DEFAULT 0 #define TEXTURE_SLOT_GAME 1 -#define TEXTURE_SLOT_UPSCALE 4 -#define TEXTURE_SLOT_POSTFX1 5 -#define TEXTURE_SLOT_POSTFX2 6 -#define TEXTURE_SLOT_MAP 7 -#define TEXTURE_SLOT_LUT 8 -#define TEXTURE_SLOT_PREFX 9 -#define TEXTURE_SLOT_BLOOM1 10 -#define TEXTURE_SLOT_BLOOM2 11 -#define TEXTURE_SLOT_MASK 12 - -#define TEXTURE_SLOT_CURSOR 2 -#define TEXTURE_SLOT_FONTS 3 +#define TEXTURE_SLOT_POSTFX1 2 +#define TEXTURE_SLOT_POSTFX2 3 +#define TEXTURE_SLOT_PREFX 4 +#define TEXTURE_SLOT_BLOOM1 5 +#define TEXTURE_SLOT_BLOOM2 6 + +#define TEXTURE_SLOT_LUT 11 +#define TEXTURE_SLOT_CURSOR 12 +#define TEXTURE_SLOT_FONTS 13 +#define TEXTURE_SLOT_MASK 14 +#define TEXTURE_SLOT_MAP 15 #define IMAGE_UNIT_BLUR 0 #define IMAGE_UNIT_FXAA 1 @@ -135,11 +134,6 @@ class Context { std::unique_ptr m_game_framebuffer; std::unique_ptr m_movie_pipeline; - std::unique_ptr m_upscale_ubo; - std::unique_ptr m_upscale_texture; - std::unique_ptr m_upscale_pipeline; - int m_current_shader = -1; - glm::vec3 m_sharpen_data; glm::uvec2 m_fxaa_work_size = { 0, 0 }; std::unique_ptr m_postfx_ubo; @@ -149,6 +143,7 @@ class Context { std::unique_ptr m_fxaa_compute_pipeline; std::unique_ptr m_mod_pipeline; + int m_current_shader = -1; // Glide only std::unique_ptr m_glide_texture; @@ -175,7 +170,7 @@ class Context { static void renderThread(void* context); void onResize(glm::uvec2 w_size, glm::uvec2 g_size, uint32_t bpp = 8); - void onShaderChange(bool texture = false); + void onShaderChange(); void onStageChange(); void setBlendState(uint32_t index); @@ -192,7 +187,7 @@ class Context { void pushVertex(const GlideVertex* vertex, glm::vec2 fix = { 0.0f, 0.0f }, glm::ivec2 offset = { 0, 0 }); void flushVertices(); - void drawQuad(int8_t flag_x = 0, glm::vec<2, int16_t> tex_ids = { 0, 0 }); + void drawQuad(int8_t flag_x = 0, int8_t flag_y = 0, int16_t tex_id = 0); inline void toggleDelayPush(bool delay) { m_delay_push = delay; } void pushObject(const std::unique_ptr& object); diff --git a/d2gl/src/graphic/frame_buffer.cpp b/d2gl/src/graphic/frame_buffer.cpp index e35b5f6..fa7312b 100644 --- a/d2gl/src/graphic/frame_buffer.cpp +++ b/d2gl/src/graphic/frame_buffer.cpp @@ -39,8 +39,7 @@ FrameBuffer::FrameBuffer(const FrameBufferCreateInfo& info) for (size_t i = 0; i < attachment_count; i++) { texture_ci.slot = info.attachments[i].slot; texture_ci.format = info.attachments[i].format; - texture_ci.min_filter = info.attachments[i].min_filter; - texture_ci.mag_filter = info.attachments[i].mag_filter; + texture_ci.filter = info.attachments[i].filter; m_textures.push_back(std::make_unique(texture_ci)); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, m_textures[i]->getId(), 0); @@ -50,17 +49,24 @@ FrameBuffer::FrameBuffer(const FrameBufferCreateInfo& info) } glDrawBuffers(attachment_count, attachments); - delete[] attachments; - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - error_log("Framebuffer is not complete!"); + auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + error_log("(%d) Framebuffer is not complete!", status); + for (size_t i = 0; i < attachment_count; i++) + trace_log("Attachment #%d size: %d x %d (%d)", i, m_textures[i]->getWidth(), m_textures[i]->getHeight(), m_textures[i]->getSlot()); + m_complete = false; + } + delete[] attachments; glBindFramebuffer(GL_FRAMEBUFFER, 0); current_binded_fbo = 0; } FrameBuffer::~FrameBuffer() { + for (auto& texture : m_textures) + texture.reset(); glDeleteFramebuffers(1, &m_id); } diff --git a/d2gl/src/graphic/frame_buffer.h b/d2gl/src/graphic/frame_buffer.h index 46f13d4..e775584 100644 --- a/d2gl/src/graphic/frame_buffer.h +++ b/d2gl/src/graphic/frame_buffer.h @@ -25,9 +25,8 @@ class Texture; struct FrameBufferAttachment { uint32_t slot = 0; std::array clear_color = { 0.0f, 0.0f, 0.0f, 1.0f }; - GLint min_filter = GL_NEAREST; - GLint mag_filter = GL_NEAREST; - GLenum format = GL_RGBA; + std::pair filter = { GL_NEAREST, GL_NEAREST }; + std::pair format = { GL_RGBA8, GL_RGBA }; }; struct FrameBufferCreateInfo { @@ -40,6 +39,7 @@ class FrameBuffer { uint32_t m_width, m_height; std::vector> m_textures; std::vector> m_clear_colors; + bool m_complete = true; public: FrameBuffer(const FrameBufferCreateInfo& info); @@ -48,10 +48,11 @@ class FrameBuffer { void bind(bool clear = true); static void unBind(); - inline const GLuint getId() const { return m_id; }; - inline Texture* getTexture(uint32_t index = 0) { return m_textures[index].get(); }; + inline const GLuint getId() const { return m_id; } + inline Texture* getTexture(uint32_t index = 0) { return m_textures[index].get(); } inline const uint32_t getWidth() const { return m_width; } inline const uint32_t getHeight() const { return m_height; } + inline bool isComplete() { return m_complete; } private: void clearBuffer(); diff --git a/d2gl/src/graphic/pipeline.cpp b/d2gl/src/graphic/pipeline.cpp index f0ba74e..ea3327a 100644 --- a/d2gl/src/graphic/pipeline.cpp +++ b/d2gl/src/graphic/pipeline.cpp @@ -24,24 +24,27 @@ namespace d2gl { -GLuint current_program = 0; -uint32_t current_blend_index = 10; - Pipeline::Pipeline(const PipelineCreateInfo& info) - : m_attachment_blends(info.attachment_blends), m_compute(info.compute) + : m_name(info.name), m_attachment_blends(info.attachment_blends), m_bindings(info.bindings), m_compute(info.compute) { m_id = glCreateProgram(); GLuint vs = 0, fs = 0, cs = 0; if (m_compute) { - cs = createShader(info.shader, GL_COMPUTE_SHADER); + cs = createShader(info.shader, GL_COMPUTE_SHADER, info.version, m_name); glAttachShader(m_id, cs); + if (cs == 0) + m_compile_success = false; } else { - vs = createShader(info.shader, GL_VERTEX_SHADER); + vs = createShader(info.shader, GL_VERTEX_SHADER, info.version, m_name); glAttachShader(m_id, vs); + if (vs == 0) + m_compile_success = false; - fs = createShader(info.shader, GL_FRAGMENT_SHADER); + fs = createShader(info.shader, GL_FRAGMENT_SHADER, info.version, m_name); glAttachShader(m_id, fs); + if (fs == 0) + m_compile_success = false; } glLinkProgram(m_id); @@ -52,8 +55,8 @@ Pipeline::Pipeline(const PipelineCreateInfo& info) glUseProgram(m_id); - if (info.bindings.size() > 0) { - for (auto& binding : info.bindings) { + if (m_compile_success && m_bindings.size() > 0) { + for (auto& binding : m_bindings) { switch (binding.type) { case BindingType::UniformBuffer: { GLuint ubo_index = glGetUniformBlockIndex(m_id, binding.name.c_str()); @@ -61,17 +64,14 @@ Pipeline::Pipeline(const PipelineCreateInfo& info) break; } case BindingType::Texture: - case BindingType::Image: { + case BindingType::Image: + case BindingType::FBTexture: { setUniform1i(binding.name, binding.value); break; } }; } } - - glUseProgram(0); - current_program = 0; - current_blend_index = 10; } Pipeline::~Pipeline() @@ -81,6 +81,9 @@ Pipeline::~Pipeline() void Pipeline::bind(uint32_t index) { + static GLuint current_program = 0; + static uint32_t current_blend_index = 10; + if (current_program == m_id && current_blend_index == index) return; @@ -94,17 +97,39 @@ void Pipeline::bind(uint32_t index) setBlendState(index); current_blend_index = index; } + + if (m_bindings.size() > 0) { + for (auto& binding : m_bindings) { + if (binding.ptr) { + if (binding.type == BindingType::Texture) { + if (const auto& ptr = *binding.tex_ptr) + ptr->bind(); + } else if (binding.type == BindingType::FBTexture) { + if (const auto& ptr = *binding.fbo_ptr) + ptr->getTexture(binding.index)->bind(); + } + } + } + } } void Pipeline::setBlendState(uint32_t index) { + static bool blend_enabled = true; + const auto& blends = m_attachment_blends[index]; if (blends[0] == BlendType::NoBlend) { - glDisable(GL_BLEND); + if (blend_enabled) { + glDisable(GL_BLEND); + blend_enabled = false; + } return; } - glEnable(GL_BLEND); + if (!blend_enabled) { + glEnable(GL_BLEND); + blend_enabled = true; + } if (App.gl_caps.independent_blending) { for (size_t i = 0; i < blends.size(); i++) { const auto factor = blendFactor(blends[i]); @@ -127,61 +152,68 @@ BlendFactors Pipeline::blendFactor(BlendType type) return { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }; } -void Pipeline::setUniform1i(const std::string& name, int value) +GLint Pipeline::getUniformLocation(const std::string& name) { bind(); + if (m_uniform_cache.find(name) != m_uniform_cache.end()) + return m_uniform_cache[name]; + + int location = glGetUniformLocation(m_id, name.c_str()); + if (location == -1) { + error("Uniform (%s) not found!", name.c_str()); + return -1; + } + + m_uniform_cache.insert({ name, location }); + return location; +} + +void Pipeline::setUniform1i(const std::string& name, int value) +{ glUniform1i(getUniformLocation(name), value); } +void Pipeline::setUniform1u(const std::string& name, uint32_t value) +{ + glUniform1ui(getUniformLocation(name), value); +} + +void Pipeline::setUniform1f(const std::string& name, float value) +{ + glUniform1f(getUniformLocation(name), value); +} + void Pipeline::setUniformVec2f(const std::string& name, const glm::vec2& value) { - bind(); glUniform2fv(getUniformLocation(name), 1, &value.x); } void Pipeline::setUniformVec4f(const std::string& name, const glm::vec4& value) { - bind(); glUniform4fv(getUniformLocation(name), 1, &value.x); } void Pipeline::setUniformMat4f(const std::string& name, const glm::mat4& matrix) { - bind(); glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, &matrix[0][0]); } -GLint Pipeline::getUniformLocation(const std::string& name) -{ - if (m_uniform_cache.find(name) != m_uniform_cache.end()) - return m_uniform_cache[name]; - - int location = glGetUniformLocation(m_id, name.c_str()); - if (location == -1) { - error("Uniform (%s) not found!", name.c_str()); - return -1; - } - - m_uniform_cache.insert({ name, location }); - return location; -} - void Pipeline::dispatchCompute(int flag, glm::ivec2 work_size, GLbitfield barrier) { - setUniform1i("u_Flag", flag); + setUniform1u("u_Flag", flag); glDispatchCompute(work_size.x, work_size.y, 1); if (barrier) glMemoryBarrier(barrier); } -GLuint Pipeline::createShader(const char* source, int type) +GLuint Pipeline::createShader(const char* source, int type, glm::vec<2, uint8_t> version, const std::string& name) { - std::string shader_src = "#version"; + std::string shader_src = "#version " + std::to_string(version.x) + std::to_string(version.y) + "0\n"; switch (type) { - case GL_VERTEX_SHADER: shader_src += " 330\n#define VERTEX 1\n"; break; - case GL_FRAGMENT_SHADER: shader_src += " 330\n#define FRAGMENT 1\n"; break; - case GL_COMPUTE_SHADER: shader_src += " 430\n#define COMPUTE 1\n"; break; + case GL_VERTEX_SHADER: shader_src += "#define VERTEX 1\n"; break; + case GL_FRAGMENT_SHADER: shader_src += "#define FRAGMENT 1\n"; break; + case GL_COMPUTE_SHADER: shader_src += "#define COMPUTE 1\n"; break; } shader_src += source; @@ -199,7 +231,9 @@ GLuint Pipeline::createShader(const char* source, int type) glGetShaderiv(id, GL_INFO_LOG_LENGTH, &lenght); char* message = (char*)_malloca(lenght * sizeof(char)); glGetShaderInfoLog(id, lenght, &lenght, message); - error_log("Shader compile failed! (%s) | %s", (type == GL_VERTEX_SHADER ? "VERTEX" : (type == GL_FRAGMENT_SHADER ? "FRAGMENT" : "COMPUTE")), message); + const char* stype = (type == GL_VERTEX_SHADER ? "VERTEX" : (type == GL_FRAGMENT_SHADER ? "FRAGMENT" : "COMPUTE")); + error_log("Shader compile failed! %s (%s) | %s", name.c_str(), stype, message); + trace_log("%s", src); glDeleteShader(id); return 0; @@ -232,32 +266,6 @@ const char* g_shader_mod = { #include "shaders/mod.glsl.h" }; -// clang-format off -const std::vector g_shader_upscale = { - { "simple-sharp-bilinear", { - #include "shaders/upscale/simple-sharp-bilinear.glsl.h" - }, true }, - { "xbr-lv2-noblend", { - #include "shaders/upscale/xbr-lv2-noblend.glsl.h" - } }, - { "xbrz-freescale", { - #include "shaders/upscale/xbrz-freescale.glsl.h" - } }, - { "2xbr-hybrid-v5-gamma", { - #include "shaders/upscale/2xbr-hybrid-v5-gamma.glsl.h" - } }, - { "aa-shader-4.0", { - #include "shaders/upscale/aa-shader-4.0.glsl.h" - } }, - { "advanced-aa", { - #include "shaders/upscale/advanced-aa.glsl.h" - } }, - { "catmull-rom", { - #include "shaders/upscale/catmull-rom.glsl.h" - }, true }, -}; -// clang-format on - const std::map> g_blend_types = { { 0, { 0, BlendType::One_Zero } }, { 2, { 1, BlendType::Zero_SColor } }, diff --git a/d2gl/src/graphic/pipeline.h b/d2gl/src/graphic/pipeline.h index f2e21da..4b1ac04 100644 --- a/d2gl/src/graphic/pipeline.h +++ b/d2gl/src/graphic/pipeline.h @@ -22,11 +22,17 @@ namespace d2gl { class UniformBuffer; +enum class ShaderType { + GLSL, + SLang, +}; + enum class BindingType { UniformBuffer, Texture, Image, TextureArray, + FBTexture, }; enum class BlendType : int8_t { @@ -43,6 +49,13 @@ struct BindingInfo { BindingType type; std::string name = ""; uint32_t value = 0; + union { + void* ptr = nullptr; + std::unique_ptr* tex_ptr; + std::unique_ptr* fbo_ptr; + std::unique_ptr* ubo_ptr; + }; + uint32_t index = 0; }; struct BlendFactors { @@ -61,7 +74,10 @@ struct UpscaleShader { }; struct PipelineCreateInfo { + std::string name = ""; const char* shader = nullptr; + ShaderType shader_type = ShaderType::GLSL; + glm::vec<2, uint8_t> version = { 3, 3 }; std::vector bindings; AttachmentBlends attachment_blends = { { BlendType::NoBlend } }; bool compute = false; @@ -69,9 +85,12 @@ struct PipelineCreateInfo { class Pipeline { GLuint m_id = 0; + std::string m_name = ""; AttachmentBlends m_attachment_blends; std::unordered_map m_uniform_cache; - bool m_compute = true; + std::vector m_bindings; + bool m_compute = false; + bool m_compile_success = true; public: Pipeline(const PipelineCreateInfo& info); @@ -80,19 +99,24 @@ class Pipeline { void bind(uint32_t index = 0); void dispatchCompute(int flag, glm::ivec2 work_size, GLbitfield barrier = 0); + GLint getUniformLocation(const std::string& name); void setUniform1i(const std::string& name, int value); + void setUniform1u(const std::string& name, uint32_t value); + void setUniform1f(const std::string& name, float value); void setUniformVec2f(const std::string& name, const glm::vec2& value); void setUniformVec4f(const std::string& name, const glm::vec4& value); void setUniformMat4f(const std::string& name, const glm::mat4& matrix); inline const GLuint getId() const { return m_id; } + inline void updateBindings(std::vector bindings) { m_bindings = bindings; } + inline bool uniformExist(const std::string& name) { return glGetUniformLocation(m_id, name.c_str()) > -1; } + inline bool isCompileSuccess() { return m_compile_success; } private: void setBlendState(uint32_t index = 0); - GLint getUniformLocation(const std::string& name); static BlendFactors blendFactor(BlendType type); - static GLuint createShader(const char* source, int type); + static GLuint createShader(const char* source, int type, glm::vec<2, uint8_t> version, const std::string& name); }; extern const char* g_shader_glide; diff --git a/d2gl/src/graphic/shaders/glide.glsl b/d2gl/src/graphic/shaders/glide.glsl index 2bb4ea3..38cfe42 100644 --- a/d2gl/src/graphic/shaders/glide.glsl +++ b/d2gl/src/graphic/shaders/glide.glsl @@ -81,7 +81,7 @@ void main() FragColor.g = u_Gamma[int(FragColor.g * 255)].g; FragColor.b = u_Gamma[int(FragColor.b * 255)].b; FragColor.a = v_Flags.z == 1u ? v_Color2.a : 1.0; - + FragColorMap = vec4(0.0); if (v_Flags.w > 0u && v_Flags.w < 10u) { @@ -93,7 +93,6 @@ void main() FragColorMask = vec4(0.0); if(v_Flags.w == 10u) FragColorMask = FragColor; - } #endif diff --git a/d2gl/src/graphic/shaders/mod.glsl b/d2gl/src/graphic/shaders/mod.glsl index 777e43d..8931b06 100644 --- a/d2gl/src/graphic/shaders/mod.glsl +++ b/d2gl/src/graphic/shaders/mod.glsl @@ -68,8 +68,9 @@ in vec2 v_Extra; uniform vec2 u_Scale; uniform vec4 u_TextMask; -uniform bool u_IsMasking = false; uniform vec4 u_Viewport; +uniform bool u_IsMasking = false; +uniform bool u_IsGlide = true; float msdf(vec3 rgb, float smoothess, float weight) { @@ -165,7 +166,7 @@ void main() FragColor.a *= (float(v_Flags.z) * 0.01); } - if (texture(u_MaskTexture, (gl_FragCoord.xy - u_Viewport.xy) / u_Viewport.zw).r > 0.1) + if (u_IsGlide && texture(u_MaskTexture, (gl_FragCoord.xy - u_Viewport.xy) / u_Viewport.zw).r > 0.1) FragColor.a = 0.0; } diff --git a/d2gl/src/graphic/shaders/mod.glsl.h b/d2gl/src/graphic/shaders/mod.glsl.h index aa5888a..e7b825b 100644 --- a/d2gl/src/graphic/shaders/mod.glsl.h +++ b/d2gl/src/graphic/shaders/mod.glsl.h @@ -38,9 +38,8 @@ "flat in uvec4 v_Flags;" "in vec2 v_Extra;" "uniform vec2 u_Scale;" -"uniform vec4 u_TextMask;" -"uniform bool u_IsMasking=false;" -"uniform vec4 u_Viewport;" +"uniform vec4 u_TextMask,u_Viewport;" +"uniform bool u_IsMasking=false,u_IsGlide=true;" "float v(vec3 v,float u,float y)" "{" "float r=max(min(v.x,v.y),min(max(v.x,v.y),v.z)),n=max(u,1.)*(r-1.+.5*y);" @@ -146,7 +145,7 @@ "if(v_Flags.z>0u)" "FragColor.w*=float(v_Flags.z)*.01;" "}" - "if(texture(u_MaskTexture,(gl_FragCoord.xy-u_Viewport.xy)/u_Viewport.zw).x>.1)" + "if(u_IsGlide&&texture(u_MaskTexture,(gl_FragCoord.xy-u_Viewport.xy)/u_Viewport.zw).x>.1)" "FragColor.w=0.;" "}" "\n#endif" \ No newline at end of file diff --git a/d2gl/src/graphic/shaders/postfx.glsl b/d2gl/src/graphic/shaders/postfx.glsl index 0028a4e..c37aa36 100644 --- a/d2gl/src/graphic/shaders/postfx.glsl +++ b/d2gl/src/graphic/shaders/postfx.glsl @@ -39,135 +39,158 @@ */ #define P(x, y) texture(x, y).rgb -#define e_t_div 16.0 -#define s_steps 16 float FxaaLuma(vec3 rgb) { - return rgb.y * (0.587 / 0.299) + rgb.x; + return rgb.y * (0.587/0.299) + rgb.x; } -vec3 FxaaPass(sampler2D tex, vec2 pos, vec2 rs) +vec3 FxaaLerp3(vec3 a, vec3 b, float amountOfA) { - vec3 rgbN = P(tex, pos + vec2(0.0, -rs.y)); - vec3 rgbW = P(tex, pos + vec2(-rs.x, 0.0)); - vec3 rgbM = P(tex, pos); - vec3 rgbE = P(tex, pos + vec2( rs.x, 0.0)); - vec3 rgbS = P(tex, pos + vec2(0.0, rs.y)); - - 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(1.0 / e_t_div, rangeMax * (1.0 / 8.0))) - 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) - 0.25) * (1.0 / 0.75); - blendL = min(3.0 / 4.0, blendL); - - vec3 rgbNW = P(tex, pos + vec2(-rs.x, -rs.y)); - vec3 rgbNE = P(tex, pos + vec2( rs.x, -rs.y)); - vec3 rgbSW = P(tex, pos + vec2(-rs.x, rs.y)); - vec3 rgbSE = P(tex, pos + vec2( rs.x, rs.y)); - - 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 ? -rs.y : -rs.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 *= (1.0 / 4.0); - - vec2 posP = posN; - vec2 offNP = horzSpan ? vec2(rs.x, 0.0) : vec2(0.0, rs.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 < s_steps; i++) - { - if(!doneN) - lumaEndN = FxaaLuma(P(tex, posN.xy)); - - if(!doneP) - lumaEndP = FxaaLuma(P(tex, posP.xy)); - - doneN = doneN || (abs(lumaEndN - lumaN) >= gradientN); - doneP = doneP || (abs(lumaEndP - lumaN) >= gradientN); - - if(doneN && doneP) - break; - - if(!doneN) - posN -= offNP; + return (vec3(-amountOfA) * b) + ((a * vec3(amountOfA)) + b); +} - 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 = P(tex, vec2(pos.x + (horzSpan ? 0.0 : subPixelOffset), pos.y + (horzSpan ? subPixelOffset : 0.0))); +vec3 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 P(tex, vec2(x, y)); +} - return (vec3(-blendL) * rgbF) + ((rgbL * vec3(blendL)) + rgbF); +vec3 FxaaPass(sampler2D tex, vec2 pos, vec2 rcpFrame, uint preset) +{ + float FXAA_EDGE_THRESHOLD = (1.0/8.0); + float FXAA_EDGE_THRESHOLD_MIN = (1.0/16.0); + float FXAA_SEARCH_THRESHOLD = (1.0/4.0); + float FXAA_SUBPIX_CAP = (3.0/4.0); + float FXAA_SUBPIX_TRIM = (1.0/4.0); + int FXAA_SEARCH_STEPS = 16; + if (preset == 2u) { + FXAA_EDGE_THRESHOLD = (1.0/8.0); + FXAA_EDGE_THRESHOLD_MIN = (1.0/24.0); + FXAA_SEARCH_THRESHOLD = (1.0/4.0); + FXAA_SUBPIX_CAP = (3.0/4.0); + FXAA_SUBPIX_TRIM = (1.0/4.0); + FXAA_SEARCH_STEPS = 24; + } else if (preset == 3u) { + FXAA_EDGE_THRESHOLD = (1.0/8.0); + FXAA_EDGE_THRESHOLD_MIN = (1.0/24.0); + FXAA_SEARCH_THRESHOLD = (1.0/4.0); + FXAA_SUBPIX_CAP = (3.0/4.0); + FXAA_SUBPIX_TRIM = (1.0/4.0); + FXAA_SEARCH_STEPS = 32; + } + + vec3 rgbN = FxaaTexOff(tex, pos.xy, ivec2( 0,-1), rcpFrame); + vec3 rgbW = FxaaTexOff(tex, pos.xy, ivec2(-1, 0), rcpFrame); + vec3 rgbM = FxaaTexOff(tex, pos.xy, ivec2( 0, 0), rcpFrame); + vec3 rgbE = FxaaTexOff(tex, pos.xy, ivec2( 1, 0), rcpFrame); + vec3 rgbS = FxaaTexOff(tex, pos.xy, ivec2( 0, 1), rcpFrame); + + 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) * (1.0/(1.0 - FXAA_SUBPIX_TRIM)); + blendL = min(FXAA_SUBPIX_CAP, blendL); + + vec3 rgbNW = FxaaTexOff(tex, pos.xy, ivec2(-1,-1), rcpFrame); + vec3 rgbNE = FxaaTexOff(tex, pos.xy, ivec2( 1,-1), rcpFrame); + vec3 rgbSW = FxaaTexOff(tex, pos.xy, ivec2(-1, 1), rcpFrame); + vec3 rgbSE = FxaaTexOff(tex, pos.xy, ivec2( 1, 1), rcpFrame); + 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(P(tex, posN.xy)); + if(!doneP) + lumaEndP = FxaaLuma(P(tex, posP.xy)); + + 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 = P(tex, vec2(pos.x + (horzSpan ? 0.0 : subPixelOffset), pos.y + (horzSpan ? subPixelOffset : 0.0))); + return FxaaLerp3(rgbL, rgbF, blendL); } #ifdef VERTEX @@ -230,7 +253,7 @@ void main() switch(v_Flags.x) { case 0u: FragColor = vec4(LumaSharpen(u_Texture0, v_TexCoord), 1.0); break; case 1u: FragColor = vec4(LumaSharpen(u_Texture1, v_TexCoord), 1.0); break; - case 2u: FragColor = vec4(FxaaPass(u_Texture0, v_TexCoord, u_RelSize), 1.0); break; + case 2u: FragColor = vec4(FxaaPass(u_Texture0, v_TexCoord, u_RelSize, v_Flags.y), 1.0); break; case 3u: FragColor = vec4(P(u_Texture0, v_TexCoord), 1.0); break; } } @@ -243,7 +266,7 @@ layout(local_size_x = 16, local_size_y = 16) in; uniform sampler2D u_InTexture; writeonly uniform image2D u_OutTexture; -uniform int u_Flag = 0; +uniform uint u_Flag = 0; void main() { @@ -251,8 +274,7 @@ void main() vec2 tex_size = vec2(textureSize(u_InTexture, 0)); vec2 v_TexCoord = (vec2(position) + vec2(0.5)) / tex_size; - vec3 color = FxaaPass(u_InTexture, v_TexCoord, vec2(1.0) / tex_size); - + vec3 color = FxaaPass(u_InTexture, v_TexCoord, vec2(1.0) / tex_size, u_Flag); imageStore(u_OutTexture, position, vec4(color, 1.0)); } diff --git a/d2gl/src/graphic/shaders/postfx.glsl.h b/d2gl/src/graphic/shaders/postfx.glsl.h index 2b5b922..948fdfd 100644 --- a/d2gl/src/graphic/shaders/postfx.glsl.h +++ b/d2gl/src/graphic/shaders/postfx.glsl.h @@ -1,88 +1,102 @@ #pragma once "#define P(x,y)texture(x,y).rgb\n" -"\n#define e_t_div 16.0\n" -"\n#define s_steps 16\n" -"float v(vec3 v)" +"float u(vec3 u)" "{" - "return v.y*(.587/.299)+v.x;" + "return u.y*(.587/.299)+u.x;" "}" -"vec3 v(sampler2D u,vec2 y,vec2 m)" +"vec3 u(vec3 u,vec3 y,float v)" "{" - "vec3 s=P(u,y+vec2(0,-m.y)),x=P(u,y+vec2(-m.x,0)),d=P(u,y),l=P(u,y+vec2(m.x,0)),n=P(u,y+vec2(0,m.y));" - "float i=v(s),a=v(x),e=v(d),k=v(l),f=v(n),r=min(e,min(min(i,a),min(f,k))),C=max(e,max(max(i,a),max(f,k))),g=C-r;" - "if(g=G;" - "float I=V?" - "-m.y:" - "-m.x;" - "if(!V)" - "i=a,f=k;" - "float w=abs(i-e),J=abs(f-e);" - "i=(i+e)*.5;" - "f=(f+e)*.5;" - "if(w=L;" + "float O=N?" + "-y.y:" + "-y.x;" + "if(!N)" + "b=C,F=p;" + "float Q=abs(b-c),R=abs(F-c);" + "b=(b+c)*.5;" + "F=(F+c)*.5;" + "if(Q=w;" - "R=R||abs(O-i)>=w;" - "if(Q&&R)" + "if(!Z)" + "X=u(P(v,S.xy));" + "if(!j)" + "Y=u(P(v,U.xy));" + "Z=Z||abs(X-b)>=Q;" + "j=j||abs(Y-b)>=Q;" + "if(Z&&j)" "break;" - "if(!Q)" - "K-=M;" - "if(!R)" - "L+=M;" + "if(!Z)" + "S-=W;" + "if(!j)" + "U+=W;" "}" - "float S=V?" - "y.x-K.x:" - "y.y-K.y,U=V?" - "L.x-y.x:" - "L.y-y.y;" - "bool W=S 0 ? LUT(FragColor) : FragColor; break; } - - FragColorMap = vec4(0.0, 0.0, 0.0, 0.0); } // ============================================================= @@ -155,7 +152,7 @@ layout(local_size_x = 16, local_size_y = 16) in; uniform sampler2D u_InTexture; writeonly uniform image2D u_OutTexture; -uniform int u_Flag = 0; +uniform uint u_Flag = 0; vec4 BlurPass17(sampler2D tex, ivec2 tc, int dir) { @@ -201,8 +198,8 @@ void main() vec4 color = vec4(0.0); switch (u_Flag) { - case 0: color = BlurPass17(u_InTexture, v_TexCoord, 0); break; - case 1: color = BlurPass17(u_InTexture, v_TexCoord, 1); break; + case 0u: color = BlurPass17(u_InTexture, v_TexCoord, 0); break; + case 1u: color = BlurPass17(u_InTexture, v_TexCoord, 1); break; } imageStore(u_OutTexture, v_TexCoord, color); diff --git a/d2gl/src/graphic/shaders/prefx.glsl.h b/d2gl/src/graphic/shaders/prefx.glsl.h index 480213e..6b5a154 100644 --- a/d2gl/src/graphic/shaders/prefx.glsl.h +++ b/d2gl/src/graphic/shaders/prefx.glsl.h @@ -17,8 +17,7 @@ "v_Flags=Flags;" "}" "\n#elif FRAGMENT\n" -"layout(location=0) out vec4 FragColor;" -"layout(location=1) out vec4 FragColorMap;layout(std140) uniform ubo_Metrics{float u_BloomExp;float u_BloomGamma;vec2 u_RelSize;};" +"layout(location=0) out vec4 FragColor;layout(std140) uniform ubo_Metrics{float u_BloomExp;float u_BloomGamma;vec2 u_RelSize;};" "uniform sampler2D u_Texture,u_BloomTexture1,u_BloomTexture2;" "uniform sampler2DArray u_LUTTexture;" "in vec2 v_TexCoord;" @@ -27,47 +26,47 @@ "\n#define CoefLuma vec3(0.2126,0.7152,0.0722)\n" "vec4 t()" "{" - "vec3 v=texture(u_Texture,v_TexCoord).xyz;" - "float u=dot(v,CoefLuma);" - "return u>.97?" - "(v=mix(vec3(dot(v,CoefLuma)),v,50.),vec4(v,1)):" + "vec3 u=texture(u_Texture,v_TexCoord).xyz;" + "float v=dot(u,CoefLuma);" + "return v>.97?" + "(u=mix(vec3(dot(u,CoefLuma)),u,50.),vec4(u,1)):" "vec4(0);" "}" -"vec4 t(sampler2D v,int u)" +"vec4 t(sampler2D u,int v)" "{" "vec4 i=vec4(0);" "vec2 f[13];" - "if(u==0)" + "if(v==0)" "for(int e=-6;e<=6;e++)" "f[e+6]=v_TexCoord+vec2(u_RelSize.x*e,0);" "else " "for(int e=-5;e<=6;e++)" "f[e+6]=v_TexCoord+vec2(0,u_RelSize.y*e);" - "i+=texture(v,f[0])*.000244140625;" - "i+=texture(v,f[1])*.0029296875;" - "i+=texture(v,f[2])*.01611328125;" - "i+=texture(v,f[3])*.0537109375;" - "i+=texture(v,f[4])*.120849609375;" - "i+=texture(v,f[5])*.193359375;" - "i+=texture(v,f[6])*.2255859375;" - "i+=texture(v,f[7])*.193359375;" - "i+=texture(v,f[8])*.120849609375;" - "i+=texture(v,f[9])*.0537109375;" - "i+=texture(v,f[10])*.01611328125;" - "i+=texture(v,f[11])*.0029296875;" - "i+=texture(v,f[12])*.000244140625;" + "i+=texture(u,f[0])*.000244140625;" + "i+=texture(u,f[1])*.0029296875;" + "i+=texture(u,f[2])*.01611328125;" + "i+=texture(u,f[3])*.0537109375;" + "i+=texture(u,f[4])*.120849609375;" + "i+=texture(u,f[5])*.193359375;" + "i+=texture(u,f[6])*.2255859375;" + "i+=texture(u,f[7])*.193359375;" + "i+=texture(u,f[8])*.120849609375;" + "i+=texture(u,f[9])*.0537109375;" + "i+=texture(u,f[10])*.01611328125;" + "i+=texture(u,f[11])*.0029296875;" + "i+=texture(u,f[12])*.000244140625;" "return i;" "}" -"vec4 t(vec4 v,vec4 u,float f)" +"vec4 t(vec4 u,vec4 v,float f)" "{" - "return v.z<1.?" - "mix(v,u,f):" - "v;" + "return u.z<1.?" + "mix(u,v,f):" + "u;" "}" "\n#define LUT_Size 32.0\n" -"vec4 t(vec4 v)" +"vec4 t(vec4 u)" "{" - "float u=(v.x*(LUT_Size-1.)+.4999)/(LUT_Size*LUT_Size),f=(v.y*(LUT_Size-1.)+.4999)/LUT_Size,e=floor(v.z*(LUT_Size-1.))/LUT_Size+u,i=ceil(v.z+1e-6*(LUT_Size-1.))/LUT_Size+u,n=clamp(max((v.z-e)/(i-e),0.),0.,32.);" + "float v=(u.x*(LUT_Size-1.)+.4999)/(LUT_Size*LUT_Size),f=(u.y*(LUT_Size-1.)+.4999)/LUT_Size,e=floor(u.z*(LUT_Size-1.))/LUT_Size+v,i=ceil(u.z+1e-6*(LUT_Size-1.))/LUT_Size+v,n=clamp(max((u.z-e)/(i-e),0.),0.,32.);" "vec4 s=texture(u_LUTTexture,vec3(vec2(e,f),v_TexIds.x-1)),r=texture(u_LUTTexture,vec3(vec2(i,f),v_TexIds.x-1));" "return t(s,r,n);" "}" @@ -85,68 +84,67 @@ "break;" "case 3u:" "case 4u:" - "vec3 v=texture(u_Texture,v_TexCoord).xyz;" + "vec3 u=texture(u_Texture,v_TexCoord).xyz;" "if(v_Flags.x==4u)" "{" - "vec3 u=texture(u_BloomTexture1,v_TexCoord).xyz;" - "u=vec3(1)-exp(-u*u_BloomExp);" - "u=pow(u,vec3(1./u_BloomGamma));" - "v=clamp(v+u,0.,1.);" + "vec3 v=texture(u_BloomTexture1,v_TexCoord).xyz;" + "v=vec3(1)-exp(-v*u_BloomExp);" + "v=pow(v,vec3(1./u_BloomGamma));" + "u=clamp(u+v,0.,1.);" "}" - "FragColor=vec4(v,1);" + "FragColor=vec4(u,1);" "FragColor=v_TexIds.x>0?" "t(FragColor):" "FragColor;" "break;" "}" - "FragColorMap=vec4(0);" "}" "\n#elif COMPUTE\n" "layout(local_size_x=16,local_size_y=16)in;" "uniform sampler2D u_InTexture;" "writeonly uniform image2D u_OutTexture;" -"uniform int u_Flag=0;" -"vec4 v(sampler2D v,ivec2 u,int i)" +"uniform uint u_Flag=0;" +"vec4 e(sampler2D u,ivec2 v,int i)" "{" "vec4 e=vec4(0);" - "ivec2 f=textureSize(v,0)-1,C[17];" + "ivec2 f=textureSize(u,0)-1,C[17];" "if(i==0)" "for(int r=-8;r<=8;r++)" - "C[r+8]=ivec2(clamp(u.x+r,1,f.x),u.y);" + "C[r+8]=ivec2(clamp(v.x+r,1,f.x),v.y);" "else " "for(int r=-8;r<=8;r++)" - "C[r+8]=ivec2(u.x,clamp(u.y+r,1,f.y));" - "e+=texelFetch(v,C[0],0)*.0000777505714898;" - "e+=texelFetch(v,C[1],0)*.0004886523773991;" - "e+=texelFetch(v,C[2],0)*.002402783593204;" - "e+=texelFetch(v,C[3],0)*.0092448129378371;" - "e+=texelFetch(v,C[4],0)*.0278352765221734;" - "e+=texelFetch(v,C[5],0)*.0655921303317756;" - "e+=texelFetch(v,C[6],0)*.120980030195482;" - "e+=texelFetch(v,C[7],0)*.174670181278773;" - "e+=texelFetch(v,C[8],0)*.197416764383733;" - "e+=texelFetch(v,C[9],0)*.174670181278773;" - "e+=texelFetch(v,C[10],0)*.120980030195482;" - "e+=texelFetch(v,C[11],0)*.0655921303317756;" - "e+=texelFetch(v,C[12],0)*.0278352765221734;" - "e+=texelFetch(v,C[13],0)*.0092448129378371;" - "e+=texelFetch(v,C[14],0)*.002402783593204;" - "e+=texelFetch(v,C[15],0)*.0004886523773991;" - "e+=texelFetch(v,C[16],0)*.0000777505714898;" + "C[r+8]=ivec2(v.x,clamp(v.y+r,1,f.y));" + "e+=texelFetch(u,C[0],0)*.0000777505714898;" + "e+=texelFetch(u,C[1],0)*.0004886523773991;" + "e+=texelFetch(u,C[2],0)*.002402783593204;" + "e+=texelFetch(u,C[3],0)*.0092448129378371;" + "e+=texelFetch(u,C[4],0)*.0278352765221734;" + "e+=texelFetch(u,C[5],0)*.0655921303317756;" + "e+=texelFetch(u,C[6],0)*.120980030195482;" + "e+=texelFetch(u,C[7],0)*.174670181278773;" + "e+=texelFetch(u,C[8],0)*.197416764383733;" + "e+=texelFetch(u,C[9],0)*.174670181278773;" + "e+=texelFetch(u,C[10],0)*.120980030195482;" + "e+=texelFetch(u,C[11],0)*.0655921303317756;" + "e+=texelFetch(u,C[12],0)*.0278352765221734;" + "e+=texelFetch(u,C[13],0)*.0092448129378371;" + "e+=texelFetch(u,C[14],0)*.002402783593204;" + "e+=texelFetch(u,C[15],0)*.0004886523773991;" + "e+=texelFetch(u,C[16],0)*.0000777505714898;" "return e;" "}" "void main()" "{" "ivec2 u=ivec2(gl_GlobalInvocationID.xy);" - "vec4 f=vec4(0);" + "vec4 v=vec4(0);" "switch(u_Flag){" - "case 0:" - "f=v(u_InTexture,u,0);" + "case 0u:" + "v=e(u_InTexture,u,0);" "break;" - "case 1:" - "f=v(u_InTexture,u,1);" + "case 1u:" + "v=e(u_InTexture,u,1);" "break;" "}" - "imageStore(u_OutTexture,u,f);" + "imageStore(u_OutTexture,u,v);" "}" "\n#endif" \ No newline at end of file diff --git a/d2gl/src/graphic/shaders/upscale/2xbr-hybrid-v5-gamma.glsl b/d2gl/src/graphic/shaders/upscale/2xbr-hybrid-v5-gamma.glsl deleted file mode 100644 index 01c34f5..0000000 --- a/d2gl/src/graphic/shaders/upscale/2xbr-hybrid-v5-gamma.glsl +++ /dev/null @@ -1,313 +0,0 @@ -/* - Hyllian's 2xBR v3.8c+ReverseAA (squared) Shader - Dithering preserved - Copyright (C) 2011/2012 Hyllian/Jararaca - sergiogdb@gmail.com - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -/* - ReverseAA part of the code - - Copyright (c) 2012, Christoph Feck - All Rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifdef VERTEX - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 TexCoord; - -uniform mat4 u_MVP; - -out vec2 v_TexCoord; - -void main() -{ - gl_Position = u_MVP * vec4(Position, 0.0, 1.0); - v_TexCoord = TexCoord; -} - -// ============================================================= -#elif FRAGMENT - -layout(location = 0) out vec4 FragColor; - -layout(std140) uniform ubo_Metrics { - vec2 u_OutSize; - vec2 u_TexSize; - vec2 u_RelSize; -}; - -uniform sampler2D u_Texture; - -in vec2 v_TexCoord; - -#define mul(a,b) (b*a) - -const float coef = 2.0; -const vec4 eq_threshold = vec4(15.0, 15.0, 15.0, 15.0); -const float y_weight = 48.0; -const float u_weight = 7.0; -const float v_weight = 6.0; -const mat3x3 yuv = mat3x3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813); -const mat3x3 yuv_weighted = mat3x3(y_weight*yuv[0], u_weight*yuv[1], v_weight*yuv[2]); -const vec4 delta = vec4(0.5, 0.5, 0.5, 0.5); -const float sharpness = 0.65; - -float lum(vec3 A, vec3 B) -{ - return abs(dot(A-B, yuv_weighted[0])); -} - -vec4 df(vec4 A, vec4 B) -{ - return vec4(abs(A-B)); -} - -bvec4 eq(vec4 A, vec4 B) -{ - return lessThan(df(A, B), vec4(15.0, 15.0, 15.0, 15.0)); -} - -bvec4 eq2(vec4 A, vec4 B) -{ - return lessThan(df(A, B), vec4(2.0, 2.0, 2.0, 2.0)); -} - -bvec4 eq3(vec4 A, vec4 B) -{ - return lessThan(df(A, B), vec4(5.0, 5.0, 5.0, 5.0)); -} - -vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) -{ - return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h)); -} - -bvec4 and(bvec4 A, bvec4 B) -{ - return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w); -} - -bvec4 or(bvec4 A, bvec4 B) -{ - return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w); -} - -#define P(x) texture(u_Texture, x).rgb - -void main() -{ - vec2 _tc = v_TexCoord; - vec2 _rs = u_RelSize; - - // A1 B1 C1 - // A0 A B C C4 - // D0 D E F F4 - // G0 G H I I4 - // G5 H5 I5 - - vec4 t1 = _tc.xxxy + vec4( -_rs.x, 0, _rs.x,-2.0 * _rs.y); // A1 B1 C1 - vec4 t2 = _tc.xxxy + vec4( -_rs.x, 0, _rs.x, -_rs.y); // A B C - vec4 t3 = _tc.xxxy + vec4( -_rs.x, 0, _rs.x, 0); // D E F - vec4 t4 = _tc.xxxy + vec4( -_rs.x, 0, _rs.x, _rs.y); // G H I - vec4 t5 = _tc.xxxy + vec4( -_rs.x, 0, _rs.x, 2.0 * _rs.y); // G5 H5 I5 - vec4 t6 = _tc.xyyy + vec4(-2.0 * _rs.x,-_rs.y, 0, _rs.y); // A0 D0 G0 - vec4 t7 = _tc.xyyy + vec4( 2.0 * _rs.x,-_rs.y, 0, _rs.y); // C4 F4 I4 - - bvec4 edr, edr_left, edr_up, px; // px = pixel, edr = edge detection rule - bvec4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up; - bvec4 nc, nc30, nc60, nc45; // new_color - vec4 fx, fx_left, fx_up, final_fx; // inequations of straight lines. - - vec2 fp = fract(_tc * u_TexSize); - - vec3 A1 = P(t1.xw); - vec3 B1 = P(t1.yw); - vec3 C1 = P(t1.zw); - - vec3 A = P(t2.xw); - vec3 B = P(t2.yw); - vec3 C = P(t2.zw); - - vec3 D = P(t3.xw); - vec3 E = P(t3.yw); - vec3 F = P(t3.zw); - - vec3 G = P(t4.xw); - vec3 H = P(t4.yw); - vec3 I = P(t4.zw); - - vec3 G5 = P(t5.xw); - vec3 H5 = P(t5.yw); - vec3 I5 = P(t5.zw); - - vec3 A0 = P(t6.xy); - vec3 D0 = P(t6.xz); - vec3 G0 = P(t6.xw); - - vec3 C4 = P(t7.xy); - vec3 F4 = P(t7.xz); - vec3 I4 = P(t7.xw); - - vec4 b = mul(mat4x3(B, D, H, F), yuv_weighted[0]); - vec4 c = mul(mat4x3(C, A, G, I), yuv_weighted[0]); - vec4 e = mul(mat4x3(E, E, E, E), yuv_weighted[0]); - vec4 a = c.yzwx; - vec4 d = b.yzwx; - vec4 f = b.wxyz; - vec4 g = c.zwxy; - vec4 h = b.zwxy; - vec4 i = c.wxyz; - - vec4 i4 = mul(mat4x3(I4, C1, A0, G5), yuv_weighted[0]); - vec4 i5 = mul(mat4x3(I5, C4, A1, G0), yuv_weighted[0]); - vec4 h5 = mul(mat4x3(H5, F4, B1, D0), yuv_weighted[0]); - vec4 f4 = h5.yzwx; - - vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 ); - vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 ); - vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 ); - vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 ); - vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 ); - vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 ); - vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 ); - vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 ); - vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 ); - - // These inequations define the line below which interpolation occurs. - fx = (Ao*fp.y+Bo*fp.x); - fx_left = (Ax*fp.y+Bx*fp.x); - fx_up = (Ay*fp.y+By*fp.x); - - //this is the only way I can keep these comparisons straight '-_- - bvec4 block1 = and(not(eq(h,h5)) , not(eq(h,i5))); - bvec4 block2 = and(not(eq(f,f4)) , not(eq(f,i4))); - bvec4 block3 = and(not(eq(h, d)) , not(eq(h, g))); - bvec4 block4 = and(not(eq(f, b)) , not(eq(f, c))); - bvec4 block5 = and(eq(e, i) , or(block2 , block1)); - - bvec4 block_comp = or(block4 , or(block3 , or(block5 , or(eq(e,g) , eq(e,c))))); - - interp_restriction_lv1 = and(notEqual(e,f) , and(notEqual(e,h) , block_comp)); - interp_restriction_lv2_left = and(notEqual(e,g) , notEqual(d,g)); - interp_restriction_lv2_up = and(notEqual(e,c) , notEqual(b,c)); - - vec4 fx45 = smoothstep(Co - delta, Co + delta, fx); - vec4 fx30 = smoothstep(Cx - delta, Cx + delta, fx_left); - vec4 fx60 = smoothstep(Cy - delta, Cy + delta, fx_up); - - edr = and(lessThan((weighted_distance(e, c, g, i, h5, f4, h, f) + 3.5) , weighted_distance(h, d, i5, f, i4, b, e, i)) , interp_restriction_lv1); - edr_left = and(lessThanEqual((coef*df(f,g)), df(h,c)), interp_restriction_lv2_left); - edr_up = and(greaterThanEqual(df(f,g), (coef*df(h,c))), interp_restriction_lv2_up); - - nc45 = and(edr, bvec4(fx45)); - nc30 = and(edr, and(edr_left, bvec4(fx30))); - nc60 = and(edr, and(edr_up , bvec4(fx60))); - - px = lessThanEqual(df(e,f) , df(e,h)); - - vec3 res = E; - - vec3 n1, n2, n3, n4, s, aa, bb, cc, dd; - - n1 = B1; n2 = B; s = E; n3 = H; n4 = H5; - aa = n2-n1; bb = s-n2; cc = n3-s; dd = n4-n3; - - vec3 t = (7. * (bb + cc) - 3. * (aa + dd)) / 16.; - - vec3 m; - m.x = (s.x < 0.5) ? 2.*s.x : 2.*(1.0-s.x); - m.y = (s.y < 0.5) ? 2.*s.y : 2.*(1.0-s.y); - m.z = (s.z < 0.5) ? 2.*s.z : 2.*(1.0-s.z); - - m = min(m, sharpness*abs(bb)); - m = min(m, sharpness*abs(cc)); - - t = clamp(t, -m, m); - - vec3 s1 = (2.*fp.y-1.)*t + s; - - n1 = D0; n2 = D; s = s1; n3 = F; n4 = F4; - aa = n2-n1; bb = s-n2; cc = n3-s; dd = n4-n3; - - t = (7. * (bb + cc) - 3. * (aa + dd)) / 16.; - - m.x = (s.x < 0.5) ? 2.*s.x : 2.*(1.0-s.x); - m.y = (s.y < 0.5) ? 2.*s.y : 2.*(1.0-s.y); - m.z = (s.z < 0.5) ? 2.*s.z : 2.*(1.0-s.z); - - m = min(m, sharpness*abs(bb)); - m = min(m, sharpness*abs(cc)); - - t = clamp(t, -m, m); - - vec3 s0 = (2.*fp.x-1.)*t + s; - - nc = or(nc30 , or(nc60 , nc45)); - - float blend = 0.0; - vec3 pix; - - vec4 r1 = mix(e, f, edr); - - bool yeseq3=false; - bvec4 yes; - - if (all(eq3(r1,e))) - { - yeseq3 = true; - pix = res = s0; - } - else - { - pix = res = E; - } - - yes = and(bvec4(yeseq3) , eq2(e, mix(f, h, px))); - - vec4 final45 = vec4(nc45) * fx45; - vec4 final30 = vec4(nc30) * fx30; - vec4 final60 = vec4(nc60) * fx60; - - vec4 maximo = max(max(final30, final60), final45); - - if (nc.x) { pix = px.x ? F : H; blend = maximo.x; if (yes.x) pix = res = s0; else res=E; } - else if (nc.y) { pix = px.y ? B : F; blend = maximo.y; if (yes.y) pix = res = s0; else res=E; } - else if (nc.z) { pix = px.z ? D : B; blend = maximo.z; if (yes.z) pix = res = s0; else res=E; } - else if (nc.w) { pix = px.w ? H : D; blend = maximo.w; if (yes.w) pix = res = s0; else res=E; } - - FragColor = vec4(clamp(mix(res, pix, blend), 0.0, 1.0), 1.0); -} - -#endif diff --git a/d2gl/src/graphic/shaders/upscale/2xbr-hybrid-v5-gamma.glsl.h b/d2gl/src/graphic/shaders/upscale/2xbr-hybrid-v5-gamma.glsl.h deleted file mode 100644 index eb7c19a..0000000 --- a/d2gl/src/graphic/shaders/upscale/2xbr-hybrid-v5-gamma.glsl.h +++ /dev/null @@ -1,181 +0,0 @@ -#pragma once - -"#ifdef VERTEX\n" -"layout(location=0) in vec2 Position;" -"layout(location=1) in vec2 TexCoord;" -"uniform mat4 u_MVP;" -"out vec2 v_TexCoord;" -"void main()" -"{" - "gl_Position=u_MVP*vec4(Position,0,1);" - "v_TexCoord=TexCoord;" -"}" -"\n#elif FRAGMENT\n" -"layout(location=0) out vec4 FragColor;layout(std140) uniform ubo_Metrics{vec2 u_OutSize;vec2 u_TexSize;vec2 u_RelSize;};" -"uniform sampler2D u_Texture;" -"in vec2 v_TexCoord;" -"\n#define mul(a,b)(b*a)\n" -"const vec4 v=vec4(15);" -"const mat3x3 u=mat3x3(.299,.587,.114,-.169,-.331,.499,.499,-.418,-.0813),n=mat3x3(48.*u[0],7.*u[1],6.*u[2]);" -"const vec4 x=vec4(.5);" -"vec4 l(vec4 m,vec4 w)" -"{" - "return vec4(abs(m-w));" -"}" -"bvec4 m(vec4 m,vec4 v)" -"{" - "return lessThan(l(m,v),vec4(15));" -"}" -"bvec4 t(vec4 m,vec4 v)" -"{" - "return lessThan(l(m,v),vec4(2));" -"}" -"bvec4 f(vec4 m,vec4 v)" -"{" - "return lessThan(l(m,v),vec4(5));" -"}" -"vec4 f(vec4 m,vec4 v,vec4 x,vec4 n,vec4 w,vec4 y,vec4 u,vec4 b)" -"{" - "return l(m,v)+l(m,x)+l(n,w)+l(n,y)+4.*l(u,b);" -"}" -"bvec4 s(bvec4 m,bvec4 w)" -"{" - "return bvec4(m.x&&w.x,m.y&&w.y,m.z&&w.z,m.w&&w.w);" -"}" -"bvec4 b(bvec4 m,bvec4 w)" -"{" - "return bvec4(m.x||w.x,m.y||w.y,m.z||w.z,m.w||w.w);" -"}" -"\n#define P(x)texture(u_Texture,x).rgb\n" -"void main()" -"{" - "vec2 v=v_TexCoord,w=u_RelSize;" - "vec4 u=v.xxxy+vec4(-w.x,0,w.x,-2.*w.y),y=v.xxxy+vec4(-w.x,0,w.x,-w.y),a=v.xxxy+vec4(-w.x,0,w.x,0),z=v.xxxy+vec4(-w.x,0,w.xy),c=v.xxxy+vec4(-w.x,0,w.x,2.*w.y),d=v.xyyy+vec4(-2.*w.x,-w.y,0,w.y),g=v.xyyy+vec4(2.*w.x,-w.y,0,w.y);" - "bvec4 i,e,o,T,r,A,C,B,D,E,F;" - "vec4 V,G,H,I;" - "vec2 J=fract(v*u_TexSize);" - "vec3 K=P(u.xw),L=P(u.yw),M=P(u.zw),N=P(y.xw),O=P(y.yw),Q=P(y.zw),R=P(a.xw),S=P(a.yw),U=P(a.zw),W=P(z.xw),X=P(z.yw),Y=P(z.zw),Z=P(c.xw),h=P(c.yw),j=P(c.zw),k=P(d.xy),p=P(d.xz),q=P(d.xw),ax=P(g.xy),an=P(g.xz),am=P(g.xw);" - "vec4 aw=mul(mat4x3(O,R,X,U),n[0]),ay=mul(mat4x3(Q,N,W,Y),n[0]),at=mul(mat4x3(S,S,S,S),n[0]),az=aw.yzwx,al=aw.wxyz,av=ay.zwxy,ab=aw.zwxy,ai=ay.wxyz,ae=mul(mat4x3(am,M,k,Z),n[0]),aD=mul(mat4x3(j,ax,K,q),n[0]),aJ=mul(mat4x3(h,an,L,p),n[0]),aE=aJ.yzwx,ag=vec4(1,-1,-1,1),ac=vec4(1,1,-1,-1),ad=vec4(1.5,.5,-.5,.5),ar=vec4(1,-1,-1,1),au=vec4(.5,2,-.5,-2),aA=vec4(1,1,-.5,0),aB=vec4(1,-1,-1,1),aC=vec4(2,.5,-2,-.5),aF=vec4(2,0,-1,.5);" - "V=ag*J.y+ac*J.x;" - "G=ar*J.y+au*J.x;" - "H=aB*J.y+aC*J.x;" - "bvec4 aS=s(not(m(ab,aJ)),not(m(ab,aD))),ao=s(not(m(al,aE)),not(m(al,ae))),aG=s(not(m(ab,az)),not(m(ab,av))),aH=s(not(m(al,aw)),not(m(al,ay))),aK=s(m(at,ai),b(ao,aS)),aT=b(aH,b(aG,b(aK,b(m(at,av),m(at,ay)))));" - "r=s(notEqual(at,al),s(notEqual(at,ab),aT));" - "A=s(notEqual(at,av),notEqual(az,av));" - "C=s(notEqual(at,ay),notEqual(aw,ay));" - "vec4 aV=smoothstep(ad-x,ad+x,V),aa=smoothstep(aA-x,aA+x,G),aL=smoothstep(aF-x,aF+x,H);" - "i=s(lessThan(f(at,ay,av,ai,aJ,aE,ab,al)+3.5,f(ab,az,aD,al,ae,aw,at,ai)),r);" - "e=s(lessThanEqual(2.*l(al,av),l(ab,ay)),A);" - "o=s(greaterThanEqual(l(al,av),2.*l(ab,ay)),C);" - "F=s(i,bvec4(aV));" - "D=s(i,s(e,bvec4(aa)));" - "E=s(i,s(o,bvec4(aL)));" - "T=lessThanEqual(l(at,al),l(at,ab));" - "vec3 aM=S,aO,aR,aX,aN,aU,aQ,aW,aY,ap;" - "aO=L;" - "aR=O;" - "aU=S;" - "aX=X;" - "aN=h;" - "aQ=aR-aO;" - "aW=aU-aR;" - "aY=aX-aU;" - "ap=aN-aX;" - "vec3 ah=(7.*(aW+aY)-3.*(aQ+ap))/16.,aZ;" - "aZ.x=aU.x<.5?" - "2.*aU.x:" - "2.*(1.-aU.x);" - "aZ.y=aU.y<.5?" - "2.*aU.y:" - "2.*(1.-aU.y);" - "aZ.z=aU.z<.5?" - "2.*aU.z:" - "2.*(1.-aU.z);" - "aZ=min(aZ,.65*abs(aW));" - "aZ=min(aZ,.65*abs(aY));" - "ah=clamp(ah,-aZ,aZ);" - "vec3 aI=(2.*J.y-1.)*ah+aU;" - "aO=p;" - "aR=R;" - "aU=aI;" - "aX=U;" - "aN=an;" - "aQ=aR-aO;" - "aW=aU-aR;" - "aY=aX-aU;" - "ap=aN-aX;" - "ah=(7.*(aW+aY)-3.*(aQ+ap))/16.;" - "aZ.x=aU.x<.5?" - "2.*aU.x:" - "2.*(1.-aU.x);" - "aZ.y=aU.y<.5?" - "2.*aU.y:" - "2.*(1.-aU.y);" - "aZ.z=aU.z<.5?" - "2.*aU.z:" - "2.*(1.-aU.z);" - "aZ=min(aZ,.65*abs(aW));" - "aZ=min(aZ,.65*abs(aY));" - "ah=clamp(ah,-aZ,aZ);" - "vec3 aq=(2.*J.x-1.)*ah+aU;" - "B=b(D,b(E,F));" - "float aj=0.;" - "vec3 ak;" - "vec4 aP=mix(at,al,i);" - "bool af=false;" - "bvec4 as;" - "ak=all(f(aP,at))?" - "(af=true,aM=aq):" - "(aM=S);" - "as=s(bvec4(af),t(at,mix(al,ab,T)));" - "vec4 bv=vec4(F)*aV,bx=vec4(D)*aa,bw=vec4(E)*aL,bk=max(max(bx,bw),bv);" - "if(B.x)" - "{" - "ak=T.x?" - "U:" - "X;" - "aj=bk.x;" - "if(as.x)" - "ak=aM=aq;" - "else " - "aM=S;" - "}" - "else " - "if(B.y)" - "{" - "ak=T.y?" - "O:" - "U;" - "aj=bk.y;" - "if(as.y)" - "ak=aM=aq;" - "else " - "aM=S;" - "}" - "else " - "if(B.z)" - "{" - "ak=T.z?" - "R:" - "O;" - "aj=bk.z;" - "if(as.z)" - "ak=aM=aq;" - "else " - "aM=S;" - "}" - "else " - "if(B.w)" - "{" - "ak=T.w?" - "X:" - "R;" - "aj=bk.w;" - "if(as.w)" - "ak=aM=aq;" - "else " - "aM=S;" - "}" - "FragColor=vec4(clamp(mix(aM,ak,aj),0.,1.),1);" -"}" -"\n#endif" \ No newline at end of file diff --git a/d2gl/src/graphic/shaders/upscale/aa-shader-4.0.glsl b/d2gl/src/graphic/shaders/upscale/aa-shader-4.0.glsl deleted file mode 100644 index 511899c..0000000 --- a/d2gl/src/graphic/shaders/upscale/aa-shader-4.0.glsl +++ /dev/null @@ -1,109 +0,0 @@ -//##############################################################// -// // -// AA Shader 4.o shader - coded by guest(r) // -// part of code by ShadX // -//##############################################################// -// Ported by Hyllian and hunterk - 2015 - -#ifdef VERTEX - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 TexCoord; - -uniform mat4 u_MVP; - -out vec2 v_TexCoord; - -void main() -{ - gl_Position = u_MVP * vec4(Position, 0.0, 1.0); - v_TexCoord = TexCoord; -} - -// ============================================================= -#elif FRAGMENT - -layout(location = 0) out vec4 FragColor; - -layout(std140) uniform ubo_Metrics { - vec2 u_OutSize; - vec2 u_TexSize; - vec2 u_RelSize; -}; - -uniform sampler2D u_Texture; - -in vec2 v_TexCoord; - -#define INTERNAL_RES 1.0 - -vec3 dt = vec3(1.0,1.0,1.0); - -vec3 texture2d (sampler2D tex, vec2 coord, vec4 yx) { - - vec3 s00 = texture(tex, coord + yx.zw).xyz; - vec3 s20 = texture(tex, coord + yx.xw).xyz; - vec3 s22 = texture(tex, coord + yx.xy).xyz; - vec3 s02 = texture(tex, coord + yx.zy).xyz; - - float m1=dot(abs(s00-s22),dt)+0.001; - float m2=dot(abs(s02-s20),dt)+0.001; - - return 0.5*(m2*(s00+s22)+m1*(s02+s20))/(m1+m2); -} - -void main() -{ - //Calculating texel coordinates - vec2 size = 4.0 * u_TexSize / INTERNAL_RES; - //vec2 size = X * (outsize.xy * SourceSize.zw) * SourceSize.xy; - vec2 inv_size = 1.0 / size; - - vec4 yx = vec4(inv_size, -inv_size); - - vec2 OGL2Pos = v_TexCoord * size; - - vec2 fp = fract(OGL2Pos); - vec2 dx = vec2(inv_size.x,0.0); - vec2 dy = vec2(0.0, inv_size.y); - vec2 g1 = vec2(inv_size.x,inv_size.y); - vec2 g2 = vec2(-inv_size.x,inv_size.y); - - vec2 pC4 = floor(OGL2Pos) * inv_size; - - // Reading the texels - vec3 C0 = texture2d(u_Texture, pC4 - g1, yx); - vec3 C1 = texture2d(u_Texture, pC4 - dy, yx); - vec3 C2 = texture2d(u_Texture, pC4 - g2, yx); - vec3 C3 = texture2d(u_Texture, pC4 - dx, yx); - vec3 C4 = texture2d(u_Texture, pC4 , yx); - vec3 C5 = texture2d(u_Texture, pC4 + dx, yx); - vec3 C6 = texture2d(u_Texture, pC4 + g2, yx); - vec3 C7 = texture2d(u_Texture, pC4 + dy, yx); - vec3 C8 = texture2d(u_Texture, pC4 + g1, yx); - - vec3 ul, ur, dl, dr; - float m1, m2; - - m1 = dot(abs(C0-C4),dt)+0.001; - m2 = dot(abs(C1-C3),dt)+0.001; - ul = (m2*(C0+C4)+m1*(C1+C3))/(m1+m2); - - m1 = dot(abs(C1-C5),dt)+0.001; - m2 = dot(abs(C2-C4),dt)+0.001; - ur = (m2*(C1+C5)+m1*(C2+C4))/(m1+m2); - - m1 = dot(abs(C3-C7),dt)+0.001; - m2 = dot(abs(C6-C4),dt)+0.001; - dl = (m2*(C3+C7)+m1*(C6+C4))/(m1+m2); - - m1 = dot(abs(C4-C8),dt)+0.001; - m2 = dot(abs(C5-C7),dt)+0.001; - dr = (m2*(C4+C8)+m1*(C5+C7))/(m1+m2); - - vec3 c11 = 0.5*((dr*fp.x+dl*(1.0-fp.x))*fp.y+(ur*fp.x+ul*(1.0-fp.x))*(1.0-fp.y)); - - FragColor = vec4(c11, 1.0); -} - -#endif diff --git a/d2gl/src/graphic/shaders/upscale/aa-shader-4.0.glsl.h b/d2gl/src/graphic/shaders/upscale/aa-shader-4.0.glsl.h deleted file mode 100644 index 735df19..0000000 --- a/d2gl/src/graphic/shaders/upscale/aa-shader-4.0.glsl.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -"#ifdef VERTEX\n" -"layout(location=0) in vec2 Position;" -"layout(location=1) in vec2 TexCoord;" -"uniform mat4 u_MVP;" -"out vec2 v_TexCoord;" -"void main()" -"{" - "gl_Position=u_MVP*vec4(Position,0,1);" - "v_TexCoord=TexCoord;" -"}" -"\n#elif FRAGMENT\n" -"layout(location=0) out vec4 FragColor;layout(std140) uniform ubo_Metrics{vec2 u_OutSize;vec2 u_TexSize;vec2 u_RelSize;};" -"uniform sampler2D u_Texture;" -"in vec2 v_TexCoord;" -"\n#define INTERNAL_RES 1.0\n" -"vec3 v=vec3(1);" -"vec3 t(sampler2D u,vec2 e,vec4 y)" -"{" - "vec3 a=texture(u,e+y.zw).xyz,n=texture(u,e+y.xw).xyz,x=texture(u,e+y.xy).xyz,l=texture(u,e+y.zy).xyz;" - "float P=dot(abs(a-x),v)+.001,d=dot(abs(l-n),v)+.001;" - "return.5*(d*(a+x)+P*(l+n))/(P+d);" -"}" -"void main()" -"{" - "vec2 e=4.*u_TexSize/INTERNAL_RES,u=1./e;" - "vec4 n=vec4(u,-u);" - "vec2 a=v_TexCoord*e,y=fract(a),x=vec2(u.x,0),d=vec2(0,u.y),z=vec2(u.xy),P=vec2(-u.x,u.y),l=floor(a)*u;" - "vec3 m=t(u_Texture,l-z,n),s=t(u_Texture,l-d,n),r=t(u_Texture,l-P,n),w=t(u_Texture,l-x,n),A=t(u_Texture,l,n),C=t(u_Texture,l+x,n),D=t(u_Texture,l+P,n),E=t(u_Texture,l+d,n),F=t(u_Texture,l+z,n),f,S,i,o;" - "float I,B;" - "I=dot(abs(m-A),v)+.001;" - "B=dot(abs(s-w),v)+.001;" - "f=(B*(m+A)+I*(s+w))/(I+B);" - "I=dot(abs(s-C),v)+.001;" - "B=dot(abs(r-A),v)+.001;" - "S=(B*(s+C)+I*(r+A))/(I+B);" - "I=dot(abs(w-E),v)+.001;" - "B=dot(abs(D-A),v)+.001;" - "i=(B*(w+E)+I*(D+A))/(I+B);" - "I=dot(abs(A-F),v)+.001;" - "B=dot(abs(C-E),v)+.001;" - "o=(B*(A+F)+I*(C+E))/(I+B);" - "vec3 T=.5*((o*y.x+i*(1.-y.x))*y.y+(S*y.x+f*(1.-y.x))*(1.-y.y));" - "FragColor=vec4(T,1);" -"}" -"\n#endif" \ No newline at end of file diff --git a/d2gl/src/graphic/shaders/upscale/advanced-aa.glsl b/d2gl/src/graphic/shaders/upscale/advanced-aa.glsl deleted file mode 100644 index 191125d..0000000 --- a/d2gl/src/graphic/shaders/upscale/advanced-aa.glsl +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright (C) 2006 guest(r) - guest.r@gmail.com - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -/* - The AdvancedAA shader is well used to: - - AA 2xscaled gfx. to its 4x absolute size, - - AA hi-res "screens" (640x480) to their 2x size or, - - AA gfx. back to it's original size (looks nice above 640x480, set scaling to 1.0) -*/ - -#ifdef VERTEX - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 TexCoord; - -uniform mat4 u_MVP; - -out vec2 v_TexCoord; - -void main() -{ - gl_Position = u_MVP * vec4(Position, 0.0, 1.0); - v_TexCoord = TexCoord; -} - -// ============================================================= -#elif FRAGMENT - -layout(location = 0) out vec4 FragColor; - -layout(std140) uniform ubo_Metrics { - vec2 u_OutSize; - vec2 u_TexSize; - vec2 u_RelSize; -}; - -uniform sampler2D u_Texture; - -in vec2 v_TexCoord; - -vec3 dt = vec3(1.,1.,1.); - -void main() -{ - float dx = u_RelSize.x * 0.5; - float dy = u_RelSize.y * 0.5; - - vec4 t1; - vec4 t2; - vec4 t3; - vec4 t4; - - t1.xy = v_TexCoord + vec2(-dx, 0); - t2.xy = v_TexCoord + vec2( dx, 0); - t3.xy = v_TexCoord + vec2( 0,-dy); - t4.xy = v_TexCoord + vec2( 0, dy); - t1.zw = v_TexCoord + vec2(-dx,-dy); - t2.zw = v_TexCoord + vec2(-dx, dy); - t3.zw = v_TexCoord + vec2( dx,-dy); - t4.zw = v_TexCoord + vec2( dx, dy); - - vec3 c00 = texture(u_Texture, t1.zw).xyz; - vec3 c10 = texture(u_Texture, t3.xy).xyz; - vec3 c20 = texture(u_Texture, t3.zw).xyz; - vec3 c01 = texture(u_Texture, t1.xy).xyz; - vec3 c11 = texture(u_Texture, v_TexCoord).xyz; - vec3 c21 = texture(u_Texture, t2.xy).xyz; - vec3 c02 = texture(u_Texture, t2.zw).xyz; - vec3 c12 = texture(u_Texture, t4.xy).xyz; - vec3 c22 = texture(u_Texture, t4.zw).xyz; - - float d1=dot(abs(c00-c22),dt)+0.0001; - float d2=dot(abs(c20-c02),dt)+0.0001; - float hl=dot(abs(c01-c21),dt)+0.0001; - float vl=dot(abs(c10-c12),dt)+0.0001; - - float k1=0.5*(hl+vl); - float k2=0.5*(d1+d2); - - vec3 t1a=(hl*(c10+c12)+vl*(c01+c21)+k1*c11)/(2.5*(hl+vl)); - vec3 t2a=(d1*(c20+c02)+d2*(c00+c22)+k2*c11)/(2.5*(d1+d2)); - - k1=dot(abs(t1a-c11),dt)+0.0001; - k2=dot(abs(t2a-c11),dt)+0.0001; - - FragColor = vec4((k1*t2a+k2*t1a)/(k1+k2), 1.0); -} - -#endif diff --git a/d2gl/src/graphic/shaders/upscale/advanced-aa.glsl.h b/d2gl/src/graphic/shaders/upscale/advanced-aa.glsl.h deleted file mode 100644 index fec1057..0000000 --- a/d2gl/src/graphic/shaders/upscale/advanced-aa.glsl.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -"#ifdef VERTEX\n" -"layout(location=0) in vec2 Position;" -"layout(location=1) in vec2 TexCoord;" -"uniform mat4 u_MVP;" -"out vec2 v_TexCoord;" -"void main()" -"{" - "gl_Position=u_MVP*vec4(Position,0,1);" - "v_TexCoord=TexCoord;" -"}" -"\n#elif FRAGMENT\n" -"layout(location=0) out vec4 FragColor;layout(std140) uniform ubo_Metrics{vec2 u_OutSize;vec2 u_TexSize;vec2 u_RelSize;};" -"uniform sampler2D u_Texture;" -"in vec2 v_TexCoord;" -"vec3 v=vec3(1);" -"void main()" -"{" - "float u=u_RelSize.x*.5,w=u_RelSize.y*.5;" - "vec4 e,z,l,d;" - "e.xy=v_TexCoord+vec2(-u,0);" - "z.xy=v_TexCoord+vec2(u,0);" - "l.xy=v_TexCoord+vec2(0,-w);" - "d.xy=v_TexCoord+vec2(0,w);" - "e.zw=v_TexCoord+vec2(-u,-w);" - "z.zw=v_TexCoord+vec2(-u,w);" - "l.zw=v_TexCoord+vec2(u,-w);" - "d.zw=v_TexCoord+vec2(u,w);" - "vec3 a=texture(u_Texture,e.zw).xyz,n=texture(u_Texture,l.xy).xyz,y=texture(u_Texture,l.zw).xyz,P=texture(u_Texture,e.xy).xyz,r=texture(u_Texture,v_TexCoord).xyz,A=texture(u_Texture,z.xy).xyz,C=texture(u_Texture,z.zw).xyz,D=texture(u_Texture,d.xy).xyz,E=texture(u_Texture,d.zw).xyz;" - "float m=dot(abs(a-E),v)+1e-4,x=dot(abs(y-C),v)+1e-4,s=dot(abs(P-A),v)+1e-4,F=dot(abs(n-D),v)+1e-4,f=.5*(s+F),i=.5*(m+x);" - "vec3 T=(s*(n+D)+F*(P+A)+f*r)/(2.5*(s+F)),B=(m*(y+C)+x*(a+E)+i*r)/(2.5*(m+x));" - "f=dot(abs(T-r),v)+1e-4;" - "i=dot(abs(B-r),v)+1e-4;" - "FragColor=vec4((f*B+i*T)/(f+i),1);" -"}" -"\n#endif" \ No newline at end of file diff --git a/d2gl/src/graphic/shaders/upscale/catmull-rom.glsl b/d2gl/src/graphic/shaders/upscale/catmull-rom.glsl deleted file mode 100644 index 7d900d2..0000000 --- a/d2gl/src/graphic/shaders/upscale/catmull-rom.glsl +++ /dev/null @@ -1,104 +0,0 @@ -/* - Bicubic Catmull-Rom 9 taps (Fast) - ported by Hyllian - 2020 - The following code is licensed under the MIT license: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae - Ported from code: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1 - Samples a texture with Catmull-Rom filtering, using 9 texture fetches instead of 16. - See http://vec3.ca/bicubic-filtering-in-fewer-taps/ for more details - ATENTION: This code only work using LINEAR filter sampling set on Retroarch! -*/ - -#ifdef VERTEX - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 TexCoord; - -uniform mat4 u_MVP; - -out vec2 v_TexCoord; - -void main() -{ - gl_Position = u_MVP * vec4(Position, 0.0, 1.0); - v_TexCoord = TexCoord; -} - -// ============================================================= -#elif FRAGMENT - -layout(location = 0) out vec4 FragColor; - -layout(std140) uniform ubo_Metrics { - vec2 u_OutSize; - vec2 u_TexSize; - vec2 u_RelSize; -}; - -uniform sampler2D u_Texture; - -in vec2 v_TexCoord; - -#define mul(c,d) (d*c) - -void main() -{ - // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding - // down the sample location to get the exact center of our "starting" texel. The starting texel will be at - // location [1, 1] in the grid, where [0, 0] is the top left corner. - vec2 samplePos = v_TexCoord * u_TexSize; - vec2 texPos1 = floor(samplePos - 0.5) + 0.5; - - // Compute the fractional offset from our starting texel to our original sample location, which we'll - // feed into the Catmull-Rom spline function to get our filter weights. - vec2 f = samplePos - texPos1; - - // Compute the Catmull-Rom weights using the fractional offset that we calculated earlier. - // These equations are pre-expanded based on our knowledge of where the texels will be located, - // which lets us avoid having to evaluate a piece-wise function. - vec2 w0 = f * (-0.5 + f * (1.0 - 0.5 * f)); - vec2 w1 = 1.0 + f * f * (-2.5 + 1.5 * f); - vec2 w2 = f * (0.5 + f * (2.0 - 1.5 * f)); - vec2 w3 = f * f * (-0.5 + 0.5 * f); - // vec2 w3 = 1.0 - w0 - w1 - w2; - - // Work out weighting factors and sampling offsets that will let us use bilinear filtering to - // simultaneously evaluate the middle 2 samples from the 4x4 grid. - vec2 w12 = w1 + w2; - vec2 offset12 = w2 / (w1 + w2); - - // Compute the final UV coordinates we'll use for sampling the texture - vec2 texPos0 = texPos1 - 1.; - vec2 texPos3 = texPos1 + 2.; - vec2 texPos12 = texPos1 + offset12; - - texPos0 *= u_RelSize; - texPos3 *= u_RelSize; - texPos12 *= u_RelSize; - - vec4 c00 = texture(u_Texture, vec2(texPos0.x, texPos0.y)); - vec4 c10 = texture(u_Texture, vec2(texPos12.x, texPos0.y)); - vec4 c20 = texture(u_Texture, vec2(texPos3.x, texPos0.y)); - - vec4 c01 = texture(u_Texture, vec2(texPos0.x, texPos12.y)); - vec4 c11 = texture(u_Texture, vec2(texPos12.x, texPos12.y)); - vec4 c21 = texture(u_Texture, vec2(texPos3.x, texPos12.y)); - - vec4 c02 = texture(u_Texture, vec2(texPos0.x, texPos3.y)); - vec4 c12 = texture(u_Texture, vec2(texPos12.x, texPos3.y)); - vec4 c22 = texture(u_Texture, vec2(texPos3.x, texPos3.y)); - - // initialize some variables - vec4 c1, c2, c3, wx, wy = vec4(0.,0.,0.,0.); - // junk vec4 used only to round out the non-square 3x4 matrices - vec4 dummy = vec4(0.,0.,0.,1.); - - wx = vec4(w0.x, w12.x, w3.x, 1.0); - wy = vec4(w0.y, w12.y, w3.y, 1.0); - - c1 = vec4(mul(wx, mat4(c00, c10, c20, dummy))); - c2 = vec4(mul(wx, mat4(c01, c11, c21, dummy))); - c3 = vec4(mul(wx, mat4(c02, c12, c22, dummy))); - - FragColor = mul(wy, mat4(c1, c2, c3, dummy)); -} - -#endif diff --git a/d2gl/src/graphic/shaders/upscale/catmull-rom.glsl.h b/d2gl/src/graphic/shaders/upscale/catmull-rom.glsl.h deleted file mode 100644 index 828b24b..0000000 --- a/d2gl/src/graphic/shaders/upscale/catmull-rom.glsl.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -"#ifdef VERTEX\n" -"layout(location=0) in vec2 Position;" -"layout(location=1) in vec2 TexCoord;" -"uniform mat4 u_MVP;" -"out vec2 v_TexCoord;" -"void main()" -"{" - "gl_Position=u_MVP*vec4(Position,0,1);" - "v_TexCoord=TexCoord;" -"}" -"\n#elif FRAGMENT\n" -"layout(location=0) out vec4 FragColor;layout(std140) uniform ubo_Metrics{vec2 u_OutSize;vec2 u_TexSize;vec2 u_RelSize;};" -"uniform sampler2D u_Texture;" -"in vec2 v_TexCoord;" -"\n#define mul(c,d)(d*c)\n" -"void main()" -"{" - "vec2 u=v_TexCoord*u_TexSize,v=floor(u-.5)+.5,t=u-v,m=t*(-.5+t*(1.-.5*t)),n=1.+t*t*(-2.5+1.5*t),y=t*(.5+t*(2.-1.5*t)),d=t*t*(-.5+.5*t),r=n+y,l=v-1.,P=v+2.,F=v+y/(n+y);" - "l*=u_RelSize;" - "P*=u_RelSize;" - "F*=u_RelSize;" - "vec4 e=texture(u_Texture,vec2(l.xy)),x=texture(u_Texture,vec2(F.x,l.y)),c=texture(u_Texture,vec2(P.x,l.y)),s=texture(u_Texture,vec2(l.x,F.y)),A=texture(u_Texture,vec2(F.xy)),C=texture(u_Texture,vec2(P.x,F.y)),D=texture(u_Texture,vec2(l.x,P.y)),E=texture(u_Texture,vec2(F.x,P.y)),G=texture(u_Texture,vec2(P.xy)),i,o,B,H,I=vec4(0),J=vec4(0,0,0,1);" - "H=vec4(m.x,r.x,d.x,1);" - "I=vec4(m.y,r.y,d.y,1);" - "i=vec4(mul(H,mat4(e,x,c,J)));" - "o=vec4(mul(H,mat4(s,A,C,J)));" - "B=vec4(mul(H,mat4(D,E,G,J)));" - "FragColor=mul(I,mat4(i,o,B,J));" -"}" -"\n#endif" \ No newline at end of file diff --git a/d2gl/src/graphic/shaders/upscale/simple-sharp-bilinear.glsl b/d2gl/src/graphic/shaders/upscale/simple-sharp-bilinear.glsl deleted file mode 100644 index 352623c..0000000 --- a/d2gl/src/graphic/shaders/upscale/simple-sharp-bilinear.glsl +++ /dev/null @@ -1,60 +0,0 @@ -/* - Author: rsn8887 (based on TheMaister) - License: Public domain - This is an integer prescale filter that should be combined - with a bilinear hardware filtering (GL_BILINEAR filter or some such) to achieve - a smooth scaling result with minimum blur. This is good for pixelgraphics - that are scaled by non-integer factors. - - The prescale factor and texel coordinates are precalculated - in the vertex shader for speed. -*/ - -#ifdef VERTEX - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 TexCoord; - -uniform mat4 u_MVP; - -out vec2 v_TexCoord; - -void main() -{ - gl_Position = u_MVP * vec4(Position, 0.0, 1.0); - v_TexCoord = TexCoord; -} - -// ============================================================= -#elif FRAGMENT - -layout(location = 0) out vec4 FragColor; - -layout(std140) uniform ubo_Metrics { - vec2 u_OutSize; - vec2 u_TexSize; - vec2 u_RelSize; -}; - -uniform sampler2D u_Texture; - -in vec2 v_TexCoord; - -void main() -{ - vec2 texel = v_TexCoord * u_TexSize; - vec2 scale = max(floor(u_OutSize / u_TexSize), vec2(1.0, 1.0)); - - vec2 texel_floored = floor(texel); - vec2 s = fract(texel); - vec2 region_range = 0.5 - 0.5 / scale; - - vec2 center_dist = s - 0.5; - vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5; - - vec2 mod_texel = texel_floored + f; - - FragColor = vec4(texture(u_Texture, mod_texel / u_TexSize).rgb, 1.0); -} - -#endif diff --git a/d2gl/src/graphic/shaders/upscale/simple-sharp-bilinear.glsl.h b/d2gl/src/graphic/shaders/upscale/simple-sharp-bilinear.glsl.h deleted file mode 100644 index 8906a0b..0000000 --- a/d2gl/src/graphic/shaders/upscale/simple-sharp-bilinear.glsl.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -"#ifdef VERTEX\n" -"layout(location=0) in vec2 Position;" -"layout(location=1) in vec2 TexCoord;" -"uniform mat4 u_MVP;" -"out vec2 v_TexCoord;" -"void main()" -"{" - "gl_Position=u_MVP*vec4(Position,0,1);" - "v_TexCoord=TexCoord;" -"}" -"\n#elif FRAGMENT\n" -"layout(location=0) out vec4 FragColor;layout(std140) uniform ubo_Metrics{vec2 u_OutSize;vec2 u_TexSize;vec2 u_RelSize;};" -"uniform sampler2D u_Texture;" -"in vec2 v_TexCoord;" -"void main()" -"{" - "vec2 u=v_TexCoord*u_TexSize,n=max(floor(u_OutSize/u_TexSize),vec2(1)),l=floor(u),v=fract(u),e=.5-.5/n,P=v-.5,d=(P-clamp(P,-e,e))*n+.5;" - "FragColor=vec4(texture(u_Texture,(l+d)/u_TexSize).xyz,1);" -"}" -"\n#endif" \ No newline at end of file diff --git a/d2gl/src/graphic/shaders/upscale/xbr-lv2-noblend.glsl b/d2gl/src/graphic/shaders/upscale/xbr-lv2-noblend.glsl deleted file mode 100644 index 05b0d12..0000000 --- a/d2gl/src/graphic/shaders/upscale/xbr-lv2-noblend.glsl +++ /dev/null @@ -1,167 +0,0 @@ -/* - Hyllian's xBR-lv2-noblend Shader - - Copyright (C) 2011-2016 Hyllian - sergiogdb@gmail.com - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - Incorporates some of the ideas from SABR shader. Thanks to Joshua Street. -*/ - -#ifdef VERTEX - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 TexCoord; - -uniform mat4 u_MVP; - -out vec2 v_TexCoord; - -void main() -{ - gl_Position = u_MVP * vec4(Position, 0.0, 1.0); - v_TexCoord = TexCoord; -} - -// ============================================================= -#elif FRAGMENT - -layout(location = 0) out vec4 FragColor; - -layout(std140) uniform ubo_Metrics { - vec2 u_OutSize; - vec2 u_TexSize; - vec2 u_RelSize; -}; - -uniform sampler2D u_Texture; - -in vec2 v_TexCoord; - -#define CoefLuma vec3(0.2126, 0.7152, 0.0722) - -vec4 df(vec4 A, vec4 B) -{ - return vec4(abs(A - B)); -} - -vec4 diff(vec4 A, vec4 B) -{ - return vec4(notEqual(A, B)); -} - -vec4 wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) -{ - return (df(a, b) + df(a, c) + df(d, e) + df(d, f) + 4.0 * df(g, h)); -} - -#define P(x) texture(u_Texture, x).rgb - -void main() -{ - vec2 _tc = v_TexCoord; - vec2 _rs = u_RelSize; - - vec4 t1 = _tc.xxxy + vec4( -_rs.x, 0.0, _rs.x, -2.0 * _rs.y); // A1 B1 C1 - vec4 t2 = _tc.xxxy + vec4( -_rs.x, 0.0, _rs.x, -_rs.y); // A B C - vec4 t3 = _tc.xxxy + vec4( -_rs.x, 0.0, _rs.x, 0.0); // D E F - vec4 t4 = _tc.xxxy + vec4( -_rs.x, 0.0, _rs.x, _rs.y); // G H I - vec4 t5 = _tc.xxxy + vec4( -_rs.x, 0.0, _rs.x, 2.0 * _rs.y); // G5 H5 I5 - vec4 t6 = _tc.xyyy + vec4(-2.0 * _rs.x, -_rs.y, 0.0, _rs.y); // A0 D0 G0 - vec4 t7 = _tc.xyyy + vec4( 2.0 * _rs.x, -_rs.y, 0.0, _rs.y); // C4 F4 I4 - - vec4 edri, edr, edr_l, edr_u; - vec4 irlv1, irlv2l, irlv2u, block_3d; - bvec4 nc, px; - vec4 fx, fx_l, fx_u; - - vec2 fp = fract(_tc * u_TexSize); - - vec3 A1 = P(t1.xw); - vec3 B1 = P(t1.yw); - vec3 C1 = P(t1.zw); - vec3 A = P(t2.xw); - vec3 B = P(t2.yw); - vec3 C = P(t2.zw); - vec3 D = P(t3.xw); - vec3 E = P(t3.yw); - vec3 F = P(t3.zw); - vec3 G = P(t4.xw); - vec3 H = P(t4.yw); - vec3 I = P(t4.zw); - vec3 G5 = P(t5.xw); - vec3 H5 = P(t5.yw); - vec3 I5 = P(t5.zw); - vec3 A0 = P(t6.xy); - vec3 D0 = P(t6.xz); - vec3 G0 = P(t6.xw); - vec3 C4 = P(t7.xy); - vec3 F4 = P(t7.xz); - vec3 I4 = P(t7.xw); - - vec4 b = CoefLuma * mat4x3(B, D, H, F); - vec4 c = CoefLuma * mat4x3(C, A, G, I); - vec4 e = CoefLuma * mat4x3(E, E, E, E); - vec4 d = b.yzwx; - vec4 f = b.wxyz; - vec4 g = c.zwxy; - vec4 h = b.zwxy; - vec4 i = c.wxyz; - - vec4 i4 = CoefLuma * mat4x3(I4, C1, A0, G5); - vec4 i5 = CoefLuma * mat4x3(I5, C4, A1, G0); - vec4 h5 = CoefLuma * mat4x3(H5, F4, B1, D0); - vec4 f4 = h5.yzwx; - - vec4 Ao = vec4(1.0, -1.0, -1.0, 1.0); - vec4 Bo = vec4(1.0, 1.0, -1.0, -1.0); - vec4 Co = vec4(1.5, 0.5, -0.5, 0.5); - vec4 Ax = vec4(1.0, -1.0, -1.0, 1.0); - vec4 Bx = vec4(0.5, 2.0, -0.5, -2.0); - vec4 Cx = vec4(1.0, 1.0, -0.5, 0.0); - vec4 Ay = vec4(1.0, -1.0, -1.0, 1.0); - vec4 By = vec4(2.0, 0.5, -2.0, -0.5); - vec4 Cy = vec4(2.0, 0.0, -1.0, 0.5); - - fx = vec4(greaterThan(Ao * fp.y + Bo * fp.x, Co)); - fx_l = vec4(greaterThan(Ax * fp.y + Bx * fp.x, Cx)); - fx_u = vec4(greaterThan(Ay * fp.y + By * fp.x, Cy)); - - irlv1 = diff(e, f) * diff(e, h); - - irlv2l = diff(e, g) * diff(d, g); - irlv2u = diff(e, c) * diff(b, c); - - vec4 wd1 = wd(e, c, g, i, h5, f4, h, f); - vec4 wd2 = wd(h, d, i5, f, i4, b, e, i); - - edri = step(wd1, wd2) * irlv1; - edr = step(wd1 + vec4(0.1, 0.1, 0.1, 0.1), wd2) * step(vec4(0.5, 0.5, 0.5, 0.5), irlv1); - edr_l = step(2.0 * df(f, g), df(h, c)) * irlv2l * edr; - edr_u = step(2.0 * df(h, c), df(f, g)) * irlv2u * edr; - - nc = bvec4(edr * (fx + edr_l * (fx_l)) + edr_u * fx_u); - - px = lessThanEqual(df(e, f), df(e, h)); - - vec3 res1 = nc.x ? px.x ? F : H : nc.y ? px.y ? B : F : nc.z ? px.z ? D : B : E; - vec3 res2 = nc.w ? px.w ? H : D : nc.z ? px.z ? D : B : nc.y ? px.y ? B : F : E; - - vec2 df12 = abs(CoefLuma * mat2x3(res1, res2) - e.xy); - - FragColor = vec4(mix(res1, res2, step(df12.x, df12.y)), 1.0); -} - -#endif diff --git a/d2gl/src/graphic/shaders/upscale/xbr-lv2-noblend.glsl.h b/d2gl/src/graphic/shaders/upscale/xbr-lv2-noblend.glsl.h deleted file mode 100644 index 15c0926..0000000 --- a/d2gl/src/graphic/shaders/upscale/xbr-lv2-noblend.glsl.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -"#ifdef VERTEX\n" -"layout(location=0) in vec2 Position;" -"layout(location=1) in vec2 TexCoord;" -"uniform mat4 u_MVP;" -"out vec2 v_TexCoord;" -"void main()" -"{" - "gl_Position=u_MVP*vec4(Position,0,1);" - "v_TexCoord=TexCoord;" -"}" -"\n#elif FRAGMENT\n" -"layout(location=0) out vec4 FragColor;layout(std140) uniform ubo_Metrics{vec2 u_OutSize;vec2 u_TexSize;vec2 u_RelSize;};" -"uniform sampler2D u_Texture;" -"in vec2 v_TexCoord;" -"\n#define CoefLuma vec3(0.2126,0.7152,0.0722)\n" -"vec4 v(vec4 x,vec4 w)" -"{" - "return vec4(abs(x-w));" -"}" -"vec4 m(vec4 x,vec4 v)" -"{" - "return vec4(notEqual(x,v));" -"}" -"vec4 m(vec4 x,vec4 w,vec4 y,vec4 u,vec4 m,vec4 z,vec4 g,vec4 F)" -"{" - "return v(x,w)+v(x,y)+v(u,m)+v(u,z)+4.*v(g,F);" -"}" -"\n#define P(x)texture(u_Texture,x).rgb\n" -"void main()" -"{" - "vec2 u=v_TexCoord,n=u_RelSize;" - "vec4 x=u.xxxy+vec4(-n.x,0,n.x,-2.*n.y),g=u.xxxy+vec4(-n.x,0,n.x,-n.y),l=u.xxxy+vec4(-n.x,0,n.x,0),s=u.xxxy+vec4(-n.x,0,n.xy),C=u.xxxy+vec4(-n.x,0,n.x,2.*n.y),F=u.xyyy+vec4(-2.*n.x,-n.y,0,n.y),a=u.xyyy+vec4(2.*n.x,-n.y,0,n.y),y,d,z,w,e,b,i,r;" - "bvec4 T,o;" - "vec4 V,A,D;" - "vec2 B=fract(u*u_TexSize);" - "vec3 E=P(x.xw),G=P(x.yw),H=P(x.zw),I=P(g.xw),J=P(g.yw),K=P(g.zw),L=P(l.xw),M=P(l.yw),N=P(l.zw),O=P(s.xw),Q=P(s.yw),R=P(s.zw),S=P(C.xw),U=P(C.yw),W=P(C.zw),X=P(F.xy),Y=P(F.xz),Z=P(F.xw),c=P(a.xy),f=P(a.xz),h=P(a.xw);" - "vec4 j=CoefLuma*mat4x3(J,L,Q,N),k=CoefLuma*mat4x3(K,I,O,R),p=CoefLuma*mat4x3(M,M,M,M),q=j.yzwx,t=j.wxyz,ax=k.zwxy,aw=j.zwxy,ay=k.wxyz,at=CoefLuma*mat4x3(h,H,X,S),an=CoefLuma*mat4x3(W,c,E,Z),au=CoefLuma*mat4x3(U,f,G,Y),aa=vec4(1,-1,-1,1),ab=vec4(1,1,-1,-1),ak=vec4(1.5,.5,-.5,.5),ai=vec4(1,-1,-1,1),ad=vec4(.5,2,-.5,-2),az=vec4(1,1,-.5,0),ag=vec4(1,-1,-1,1),al=vec4(2,.5,-2,-.5),aF=vec4(2,0,-1,.5);" - "V=vec4(greaterThan(aa*B.y+ab*B.x,ak));" - "A=vec4(greaterThan(ai*B.y+ad*B.x,az));" - "D=vec4(greaterThan(ag*B.y+al*B.x,aF));" - "e=m(p,t)*m(p,aw);" - "b=m(p,ax)*m(q,ax);" - "i=m(p,k)*m(j,k);" - "vec4 ap=m(p,k,ax,ay,au,au.yzwx,aw,t),ae=m(aw,q,an,t,at,j,p,ay);" - "y=step(ap,ae)*e;" - "d=step(ap+vec4(.1),ae)*step(vec4(.5),e);" - "z=step(2.*v(t,ax),v(aw,k))*b*d;" - "w=step(2.*v(aw,k),v(t,ax))*i*d;" - "T=bvec4(d*(V+z*A)+w*D);" - "o=lessThanEqual(v(p,t),v(p,aw));" - "vec3 aM=T.x?" - "o.x?" - "N:" - "Q:" - "T.y?" - "o.y?" - "J:" - "N:" - "T.z?" - "o.z?" - "L:" - "J:" - "M,aA=T.w?" - "o.w?" - "Q:" - "L:" - "T.z?" - "o.z?" - "L:" - "J:" - "T.y?" - "o.y?" - "J:" - "N:" - "M;" - "vec2 aB=abs(CoefLuma*mat2x3(aM,aA)-p.xy);" - "FragColor=vec4(mix(aM,aA,step(aB.x,aB.y)),1);" -"}" -"\n#endif" \ No newline at end of file diff --git a/d2gl/src/graphic/shaders/upscale/xbrz-freescale.glsl b/d2gl/src/graphic/shaders/upscale/xbrz-freescale.glsl deleted file mode 100644 index 76980c8..0000000 --- a/d2gl/src/graphic/shaders/upscale/xbrz-freescale.glsl +++ /dev/null @@ -1,309 +0,0 @@ -/* - Hyllian's xBR-vertex code and texel mapping - - Copyright (C) 2011/2016 Hyllian - sergiogdb@gmail.com - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -// This shader also uses code and/or concepts from xBRZ as it appears -// in the Desmume source code. The license for which is as follows: - -// **************************************************************************** -// * This file is part of the HqMAME project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// * * -// * Additionally and as a special exception, the author gives permission * -// * to link the code of this program with the MAME library (or with modified * -// * versions of MAME that use the same license as MAME), and distribute * -// * linked combinations including the two. You must obey the GNU General * -// * Public License in all respects for all of the code used other than MAME. * -// * If you modify this file, you may extend this exception to your version * -// * of the file, but you are not obligated to do so. If you do not wish to * -// * do so, delete this exception statement from your version. * -// **************************************************************************** - -#ifdef VERTEX - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 TexCoord; - -uniform mat4 u_MVP; - -out vec2 v_TexCoord; - -void main() -{ - gl_Position = u_MVP * vec4(Position, 0.0, 1.0); - v_TexCoord = TexCoord; -} - -// ============================================================= -#elif FRAGMENT - -layout(location = 0) out vec4 FragColor; - -layout(std140) uniform ubo_Metrics { - vec2 u_OutSize; - vec2 u_TexSize; - vec2 u_RelSize; -}; - -uniform sampler2D u_Texture; - -in vec2 v_TexCoord; - -float DistCalc(vec3 pixA, vec3 pixB) -{ - const vec3 w = vec3(0.2627, 0.6780, 0.0593); - const float scaleB = 0.5 / (1.0 - w.b); - const float scaleR = 0.5 / (1.0 - w.r); - vec3 diff = pixA - pixB; - float Y = dot(diff.rgb, w); - float Cb = scaleB * (diff.b - Y); - float Cr = scaleR * (diff.r - Y); - - return sqrt((Y * Y) + (Cb * Cb) + (Cr * Cr)); -} - -bool IsPixEq(const vec3 pixA, const vec3 pixB) -{ - return (DistCalc(pixA, pixB) < 30.0 / 255.0); -} - -float GetLeftRatio(vec2 center, vec2 origin, vec2 dir, vec2 scale) -{ - vec2 P0 = center - origin; - vec2 proj = dir * (dot(P0, dir) / dot(dir, dir)); - vec2 distv = P0 - proj; - vec2 orth = vec2(-dir.y, dir.x); - float side = sign(dot(P0, orth)); - float v = side * length(distv * scale); - - return smoothstep(-sqrt(2.0) / 2.0, sqrt(2.0) / 2.0, v); -} - -#define eq(a,b) (a == b) -#define neq(a,b) (a != b) - -//[ -vec2 coord; -//] -#define P(x,y) texture(u_Texture, coord + u_RelSize * vec2(x, y)).rgb - -void main() -{ - //--------------------------------------- - // Input Pixel Mapping: -|x|x|x|- - // x|A|B|C|x - // x|D|E|F|x - // x|G|H|I|x - // -|x|x|x|- - - vec2 scale = u_OutSize * u_RelSize; - vec2 pos = fract(v_TexCoord * u_TexSize) - vec2(0.5, 0.5); - coord = v_TexCoord - pos * u_RelSize; - - vec3 A = P(-1.,-1.); - vec3 B = P( 0.,-1.); - vec3 C = P( 1.,-1.); - vec3 D = P(-1., 0.); - vec3 E = P( 0., 0.); - vec3 F = P( 1., 0.); - vec3 G = P(-1., 1.); - vec3 H = P( 0., 1.); - vec3 I = P( 1., 1.); - - // blend_res Mapping: x|y| - // w|z| - ivec4 blend_res = ivec4(0, 0, 0, 0); - - // Preprocess corners - // Pixel Tap Mapping: -|-|-|-|- - // -|-|B|C|- - // -|D|E|F|x - // -|G|H|I|x - // -|-|x|x|- - if (!((eq(E,F) && eq(H,I)) || (eq(E,H) && eq(F,I)))) - { - float dist_hf = DistCalc(G, E) + DistCalc(E, C) + DistCalc(P(0,2), I) + DistCalc(I, P(2.,0.)) + (4.0 * DistCalc(H, F)); - float dist_ei = DistCalc(D, H) + DistCalc(H, P(1,2)) + DistCalc(B, F) + DistCalc(F, P(2.,1.)) + (4.0 * DistCalc(E, I)); - bool dom_grad = (3.6 * dist_hf) < dist_ei; - blend_res.z = ((dist_hf < dist_ei) && neq(E,F) && neq(E,H)) ? ((dom_grad) ? 2 : 1) : 0; - } - - // Pixel Tap Mapping: -|-|-|-|- - // -|A|B|-|- - // x|D|E|F|- - // x|G|H|I|- - // -|x|x|-|- - if (!((eq(D,E) && eq(G,H)) || (eq(D,G) && eq(E,H)))) - { - float dist_ge = DistCalc(P(-2.,1.), D) + DistCalc(D, B) + DistCalc(P(-1.,2.), H) + DistCalc(H, F) + (4.0 * DistCalc(G, E)); - float dist_dh = DistCalc(P(-2.,0.), G) + DistCalc(G, P(0.,2.)) + DistCalc(A, E) + DistCalc(E, I) + (4.0 * DistCalc(D, H)); - bool dom_grad = (3.6 * dist_dh) < dist_ge; - blend_res.w = ((dist_ge > dist_dh) && neq(E,D) && neq(E,H)) ? ((dom_grad) ? 2 : 1) : 0; - } - - // Pixel Tap Mapping: -|-|x|x|- - // -|A|B|C|x - // -|D|E|F|x - // -|-|H|I|- - // -|-|-|-|- - if (!((eq(B,C) && eq(E,F)) || (eq(B,E) && eq(C,F)))) - { - float dist_ec = DistCalc(D, B) + DistCalc(B, P(1.,-2.)) + DistCalc(H, F) + DistCalc(F, P(2.,-1.)) + (4.0 * DistCalc(E, C)); - float dist_bf = DistCalc(A, E) + DistCalc(E, I) + DistCalc(P(0.,-2.), C) + DistCalc(C, P(2.,0.)) + (4.0 * DistCalc(B, F)); - bool dom_grad = (3.6 * dist_bf) < dist_ec; - blend_res.y = ((dist_ec > dist_bf) && neq(E,B) && neq(E,F)) ? ((dom_grad) ? 2 : 1) : 0; - } - - // Pixel Tap Mapping: -|x|x|-|- - // x|A|B|C|- - // x|D|E|F|- - // -|G|H|-|- - // -|-|-|-|- - if (!((eq(A,B) && eq(D,E)) || (eq(A,D) && eq(B,E)))) - { - float dist_db = DistCalc(P(-2.,0.), A) + DistCalc(A, P(0.,-2.)) + DistCalc(G, E) + DistCalc(E, C) + (4.0 * DistCalc(D, B)); - float dist_ae = DistCalc(P(-2.,-1.), D) + DistCalc(D, H) + DistCalc(P(-1.,-2.), B) + DistCalc(B, F) + (4.0 * DistCalc(A, E)); - bool dom_grad = (3.6 * dist_db) < dist_ae; - blend_res.x = ((dist_db < dist_ae) && neq(E,D) && neq(E,B)) ? ((dom_grad) ? 2 : 1) : 0; - } - - vec3 res = E; - - // Pixel Tap Mapping: -|-|-|-|- - // -|-|B|C|- - // -|D|E|F|x - // -|G|H|I|x - // -|-|x|x|- - if(blend_res.z != 0) - { - float dist_fg = DistCalc(F, G); - float dist_hc = DistCalc(H, C); - bool line_blend = (blend_res.z == 2 || - !((blend_res.y != 0 && !IsPixEq(E, G)) || (blend_res.w != 0 && !IsPixEq(E, C)) || - (IsPixEq(G, H) && IsPixEq(H, I) && IsPixEq(I, F) && IsPixEq(F, C) && !IsPixEq(E, I)))); - - vec2 origin = vec2(0.0, 1.0 / sqrt(2.0)); - vec2 dir = vec2(1.0, -1.0); - - if(line_blend) - { - bool curve_line = (2.2 * dist_fg <= dist_hc) && neq(E,G) && neq(D,G); - bool steep_line = (2.2 * dist_hc <= dist_fg) && neq(E,C) && neq(B,C); - origin = curve_line ? vec2(0.0, 0.25) : vec2(0.0, 0.5); - dir.x += curve_line ? 1.0: 0.0; - dir.y -= steep_line ? 1.0: 0.0; - } - - vec3 blend_pix = mix(H, F, step(DistCalc(E, F), DistCalc(E, H))); - res = mix(res, blend_pix, GetLeftRatio(pos, origin, dir, scale)); - } - - // Pixel Tap Mapping: -|-|-|-|- - // -|A|B|-|- - // x|D|E|F|- - // x|G|H|I|- - // -|x|x|-|- - if(blend_res.w != 0) - { - float dist_ha = DistCalc(H, A); - float dist_di = DistCalc(D, I); - bool line_blend = (blend_res.w == 2 || - !((blend_res.z != 0 && !IsPixEq(E, A)) || (blend_res.x != 0 && !IsPixEq(E, I)) || - (IsPixEq(A, D) && IsPixEq(D, G) && IsPixEq(G, H) && IsPixEq(H, I) && !IsPixEq(E, G)))); - - vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0); - vec2 dir = vec2(1.0, 1.0); - - if(line_blend) - { - bool curve_line = (2.2 * dist_ha <= dist_di) && neq(E,A) && neq(B,A); - bool steep_line = (2.2 * dist_di <= dist_ha) && neq(E,I) && neq(F,I); - origin = curve_line ? vec2(-0.25, 0.0) : vec2(-0.5, 0.0); - dir.y += curve_line ? 1.0: 0.0; - dir.x += steep_line ? 1.0: 0.0; - } - - vec3 blend_pix = mix(H, D, step(DistCalc(E, D), DistCalc(E, H))); - res = mix(res, blend_pix, GetLeftRatio(pos, origin, dir, scale)); - } - - // Pixel Tap Mapping: -|-|x|x|- - // -|A|B|C|x - // -|D|E|F|x - // -|-|H|I|- - // -|-|-|-|- - if(blend_res.y != 0) - { - float dist_bi = DistCalc(B, I); - float dist_fa = DistCalc(F, A); - bool line_blend = (blend_res.y == 2 || - !((blend_res.x != 0 && !IsPixEq(E, I)) || (blend_res.z != 0 && !IsPixEq(E, A)) || - (IsPixEq(I, F) && IsPixEq(F, C) && IsPixEq(C, B) && IsPixEq(B, A) && !IsPixEq(E, C)))); - - vec2 origin = vec2(1.0 / sqrt(2.0), 0.0); - vec2 dir = vec2(-1.0, -1.0); - - if(line_blend) - { - bool curve_line = (2.2 * dist_bi <= dist_fa) && neq(E,I) && neq(H,I); - bool steep_line = (2.2 * dist_fa <= dist_bi) && neq(E,A) && neq(D,A); - origin = curve_line ? vec2(0.25, 0.0) : vec2(0.5, 0.0); - dir.y -= curve_line ? 1.0: 0.0; - dir.x -= steep_line ? 1.0: 0.0; - } - - vec3 blend_pix = mix(F, B, step(DistCalc(E, B), DistCalc(E, F))); - res = mix(res, blend_pix, GetLeftRatio(pos, origin, dir, scale)); - } - - // Pixel Tap Mapping: -|x|x|-|- - // x|A|B|C|- - // x|D|E|F|- - // -|G|H|-|- - // -|-|-|-|- - if(blend_res.x != 0) - { - float dist_dc = DistCalc(D, C); - float dist_bg = DistCalc(B, G); - bool line_blend = (blend_res.x == 2 || - !((blend_res.w != 0 && !IsPixEq(E, C)) || (blend_res.y != 0 && !IsPixEq(E, G)) || - (IsPixEq(C, B) && IsPixEq(B, A) && IsPixEq(A, D) && IsPixEq(D, G) && !IsPixEq(E, A)))); - - vec2 origin = vec2(0.0, -1.0 / sqrt(2.0)); - vec2 dir = vec2(-1.0, 1.0); - - if(line_blend) - { - bool curve_line = (2.2 * dist_dc <= dist_bg) && neq(E,C) && neq(F,C); - bool steep_line = (2.2 * dist_bg <= dist_dc) && neq(E,G) && neq(H,G); - origin = curve_line ? vec2(0.0, -0.25) : vec2(0.0, -0.5); - dir.x -= curve_line ? 1.0: 0.0; - dir.y += steep_line ? 1.0: 0.0; - } - - vec3 blend_pix = mix(D, B, step(DistCalc(E, B), DistCalc(E, D))); - res = mix(res, blend_pix, GetLeftRatio(pos, origin, dir, scale)); - } - - FragColor = vec4(res, 1.0); -} - -#endif diff --git a/d2gl/src/graphic/shaders/upscale/xbrz-freescale.glsl.h b/d2gl/src/graphic/shaders/upscale/xbrz-freescale.glsl.h deleted file mode 100644 index dfb86ff..0000000 --- a/d2gl/src/graphic/shaders/upscale/xbrz-freescale.glsl.h +++ /dev/null @@ -1,167 +0,0 @@ -#pragma once - -"#ifdef VERTEX\n" -"layout(location=0) in vec2 Position;" -"layout(location=1) in vec2 TexCoord;" -"uniform mat4 u_MVP;" -"out vec2 v_TexCoord;" -"void main()" -"{" - "gl_Position=u_MVP*vec4(Position,0,1);" - "v_TexCoord=TexCoord;" -"}" -"\n#elif FRAGMENT\n" -"layout(location=0) out vec4 FragColor;layout(std140) uniform ubo_Metrics{vec2 u_OutSize;vec2 u_TexSize;vec2 u_RelSize;};" -"uniform sampler2D u_Texture;" -"in vec2 v_TexCoord;" -"float q(vec3 v,vec3 e)" -"{" - "const vec3 s=vec3(.2627,.678,.0593);" - "vec3 u=v-e;" - "float q=dot(u.xyz,s),y=.5/(1.-s.z)*(u.z-q),b=.5/(1.-s.x)*(u.x-q);" - "return sqrt(q*q+y*y+b*b);" -"}" -"bool n(const vec3 v,const vec3 s)" -"{" - "return q(v,s)<30./255.;" -"}" -"float n(vec2 v,vec2 s,vec2 q,vec2 u)" -"{" - "vec2 x=v-s,b=q*(dot(x,q)/dot(q,q)),y=vec2(-q.y,q.x);" - "float m=sign(dot(x,y)),n=m*length((x-b)*u);" - "return smoothstep(-sqrt(2.)/2.,sqrt(2.)/2.,n);" -"}" -"\n#define eq(a,b)(a==b)\n" -"\n#define neq(a,b)(a!=b)\n" -"vec2 coord;" -"\n#define P(x,y)texture(u_Texture,coord+u_RelSize*vec2(x,y)).rgb\n" -"void main()" -"{" - "vec2 s=u_OutSize*u_RelSize,v=fract(v_TexCoord*u_TexSize)-vec2(.5);" - "coord=v_TexCoord-v*u_RelSize;" - "vec3 u=P(-1.,-1.),x=P(0.,-1.),y=P(1.,-1.),b=P(-1.,0.),e=P(0.,0.),a=P(1.,0.),d=P(-1.,1.),z=P(0.,1.),c=P(1.,1.);" - "ivec4 m=ivec4(0,0,0,0);" - "if(!(eq(e,a)&&eq(z,c)||eq(e,z)&&eq(a,c)))" - "{" - "float i=q(d,e)+q(e,y)+q(P(0,2),c)+q(c,P(2.,0.))+4.*q(z,a),w=q(b,z)+q(z,P(1,2))+q(x,a)+q(a,P(2.,1.))+4.*q(e,c);" - "m.z=iw&&neq(e,b)&&neq(e,z)?" - "3.6*ww&&neq(e,x)&&neq(e,a)?" - "3.6*w& fbo, uint32_t i const auto width = fbo->getWidth(); const auto height = fbo->getHeight(); - bind(); + bind(true); glCopyTexSubImage2D(m_target, 0, (m_width - width) / 2, (m_height - height) / 2, 0, 0, width, height); } @@ -133,14 +137,4 @@ TextureData Texture::fillImage(ImageData image, uint32_t div_x, uint32_t div_y) return texture_data; } -GLint Texture::getInternalFormat(GLenum format) -{ - switch (format) { - case GL_RGBA: return GL_RGBA8; - case GL_BGRA: return GL_RGBA8; - case GL_RED: return GL_R8; - } - return GL_RGBA8; -} - } \ No newline at end of file diff --git a/d2gl/src/graphic/texture.h b/d2gl/src/graphic/texture.h index 578fc3a..747f979 100644 --- a/d2gl/src/graphic/texture.h +++ b/d2gl/src/graphic/texture.h @@ -32,10 +32,11 @@ struct TextureData { struct TextureCreateInfo { uint32_t slot = 0; glm::uvec2 size = { 0, 0 }; - GLint min_filter = GL_NEAREST; - GLint mag_filter = GL_NEAREST; + std::pair filter = { GL_NEAREST, GL_NEAREST }; uint32_t layer_count = 1; - GLenum format = GL_RGBA; + std::pair format = { GL_RGBA8, GL_RGBA }; + std::pair wrap_mode = { GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }; + bool mip_map = false; }; class Texture { @@ -49,7 +50,7 @@ class Texture { Texture(const TextureCreateInfo& info); ~Texture(); - void bind(); + void bind(bool force = false); void bindImage(uint32_t unit = 0); void fill(const uint8_t* pixels, uint32_t width, uint32_t height, uint32_t offset_x = 0, uint32_t offset_y = 0, uint32_t layer = 0); @@ -60,9 +61,6 @@ class Texture { inline const uint32_t getSlot() const { return m_slot; }; inline const uint32_t getWidth() const { return m_width; } inline const uint32_t getHeight() const { return m_height; } - -private: - static GLint getInternalFormat(GLenum format); }; } \ No newline at end of file diff --git a/d2gl/src/graphic/upscaler.cpp b/d2gl/src/graphic/upscaler.cpp new file mode 100644 index 0000000..31eb0fb --- /dev/null +++ b/d2gl/src/graphic/upscaler.cpp @@ -0,0 +1,585 @@ +/* + D2GL: Diablo 2 LoD Glide/DDraw to OpenGL Wrapper. + Copyright (C) 2023 Bayaraa + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pch.h" +#include "upscaler.h" +#include "helpers.h" +#include "option/ini.h" + +#include + +namespace d2gl { + +Upscaler::Upscaler() +{ + auto buffer = helpers::loadFile("shaders\\list.txt"); + if (!buffer.size) + return; + + std::string preset_list((const char*)buffer.data, buffer.size); + delete[] buffer.data; + + auto lines = helpers::strToLines(preset_list); + if (App.direct) { + std::string shader_path = helpers::getCurrentDir() + "data\\shaders\\"; + if (std::filesystem::is_directory(shader_path)) { + for (const auto& p : std::filesystem::recursive_directory_iterator(shader_path)) { + if (std::filesystem::is_directory(p)) + continue; + + std::string extension = p.path().extension().string(); + helpers::strToLower(extension); + if (extension == ".slangp") { + std::string path = p.path().string(); + path.erase(0, shader_path.length()); + lines.push_back(path); + } + } + } + } + + helpers::replaceAll(App.shader.preset, "/", "\\"); + for (auto& line : lines) { + helpers::trimString(line, "\t\n\v\f\r "); + auto buf = helpers::loadFile("shaders\\" + line); + if (!buf.size) + return; + + size_t pass_count = 1; + std::string preset_source((const char*)buf.data, buf.size); + delete[] buf.data; + + auto pos = preset_source.find("shaders ="); + if (pos == std::string::npos) + pos = preset_source.find("shaders="); + if (pos != std::string::npos) { + auto pos2 = preset_source.find("\n", pos); + auto count_str = preset_source.substr(pos, pos2 - pos - 1); + helpers::trimString(count_str, "\t\n\v\f\r "); + count_str.erase(std::remove_if(count_str.begin(), count_str.end(), (int (*)(int))std::isspace), count_str.end()); + count_str = count_str.substr(8); + count_str.erase(std::remove(count_str.begin(), count_str.end(), '"'), count_str.end()); + pass_count = std::stoul(count_str); + } + + std::string name = line + " (" + std::to_string(pass_count) + " Pass" + (pass_count > 1 ? "es" : "") + ")"; + App.shader.presets.items.push_back({ name, line }); + if (App.shader.preset == line) { + App.shader.presets.selected = App.shader.presets.items.size() - 1; + App.shader.selected = App.shader.presets.selected; + } + } +} + +bool Upscaler::loadPreset() +{ + const auto preset_name = App.shader.presets.items[App.shader.presets.selected].value; + std::string preset_path = "shaders\\" + preset_name; + + auto buffer = helpers::loadFile(preset_path); + if (!buffer.size) + return false; + + std::string preset_source((const char*)buffer.data, buffer.size); + delete[] buffer.data; + + m_passes.clear(); + m_textures.clear(); + std::unordered_map texture_info; + + auto lines = helpers::strToLines(preset_source); + for (auto& line : lines) { + line = line.substr(0, line.find("#", 0)); + line.erase(std::remove_if(line.begin(), line.end(), (int (*)(int))std::isspace), line.end()); + if (line.size() == 0) + continue; + + size_t pos = line.find('='); + if (pos == std::string::npos) + continue; + + helpers::trimString(line, "\t\n\v\f\r "); + std::string value = line.substr(pos + 1, line.size()); + value.erase(std::remove(value.begin(), value.end(), '"'), value.end()); + if (value.size() == 0) + continue; + + std::string var_str = line.substr(0, pos); + + if (m_passes.empty() && var_str == "shaders") { + const size_t count = std::stoul(value); + for (size_t i = 0; i < count; i++) + m_passes.push_back({ "Pass #" + std::to_string(i + 1) }); + continue; + } + + std::string var_name, index_s; + for (const auto& c : var_str) { + if (isdigit(c)) + index_s += c; + else + var_name += c; + } + + int index = 0; + if (!index_s.empty()) + index = std::stoul(index_s); + bool pass_data = index < (int)m_passes.size(); + + if (var_name == "shader" && pass_data) { + auto shader_path = helpers::filePathFix(preset_path, value); + if (!prepareShader(m_passes[index], shader_path)) + return false; + } else if (var_name == "alias" && pass_data) + m_passes[index].name = value; + else if (var_name == "filter_linear" && pass_data) + m_passes[index].linear_filter = (value == "true" || value == "1"); + else if (var_name == "scale_type" && pass_data) { + if (value == "viewport") + m_passes[index].scale_type = { ScaleType::Viewport, ScaleType::Viewport }; + else if (value == "absolute") + m_passes[index].scale_type = { ScaleType::Absolute, ScaleType::Absolute }; + } else if (var_name == "scale_type_x" && pass_data) { + if (value == "viewport") + m_passes[index].scale_type.x = ScaleType::Viewport; + else if (value == "absolute") + m_passes[index].scale_type.x = ScaleType::Absolute; + } else if (var_name == "scale_type_y" && pass_data) { + if (value == "viewport") + m_passes[index].scale_type.y = ScaleType::Viewport; + else if (value == "absolute") + m_passes[index].scale_type.y = ScaleType::Absolute; + } else if (var_name == "scale" && pass_data) + m_passes[index].scale_size = { std::stof(value), std::stof(value) }; + else if (var_name == "scale_x" && pass_data) + m_passes[index].scale_size.x = std::stof(value); + else if (var_name == "scale_y" && pass_data) + m_passes[index].scale_size.y = std::stof(value); + else if (var_str == "textures") { + const auto segmets = helpers::splitToVector(value, ';'); + for (auto& p : segmets) + texture_info.insert({ p, {} }); + } else { + if (texture_info.find(var_str) != texture_info.end()) + texture_info[var_str].path = helpers::filePathFix(preset_path, value); + else { + std::string tex_name; + uint8_t tex_var = 0; + if (auto pos = var_str.find("_linear"); pos != std::string::npos) { + tex_name = var_str.substr(0, pos); + tex_var = 1; + } else if (auto pos = var_str.find("_mipmap"); pos != std::string::npos) { + tex_name = var_str.substr(0, pos); + tex_var = 2; + } else if (auto pos = var_str.find("_wrap_mode"); pos != std::string::npos) { + tex_name = var_str.substr(0, pos); + tex_var = 3; + } + if (tex_name != "" && texture_info.find(tex_name) != texture_info.end()) { + switch (tex_var) { + case 1: texture_info[tex_name].linear = (value == "true" || value == "1"); break; + case 2: texture_info[tex_name].mip_map = (value == "true" || value == "1"); break; + case 3: texture_info[tex_name].wrap_mode = (value == "mirrored_repeat") ? GL_MIRRORED_REPEAT : GL_CLAMP_TO_EDGE; break; + } + } + } + } + } + + size_t tex_slot = m_passes.size() + 1; + for (auto& p : texture_info) { + auto image_data = helpers::loadImage(p.second.path, false); + if (image_data.data) { + TextureCreateInfo texture_ci; + texture_ci.size = { image_data.width, image_data.height }; + texture_ci.slot = tex_slot++; + if (p.second.linear) + texture_ci.filter = { GL_LINEAR, GL_LINEAR }; + texture_ci.wrap_mode = { p.second.wrap_mode, p.second.wrap_mode }; + texture_ci.mip_map = p.second.mip_map; + m_textures.insert({ p.first, Context::createTexture(texture_ci) }); + + m_textures[p.first]->fillImage(image_data); + helpers::clearImage(image_data); + } + } + + option::saveString("Graphic", "shader_preset", preset_name); + return true; +} + +void Upscaler::loadDefaultPreset() +{ + const std::string defalut_preset = "bilinear.slangp"; + for (size_t i = 0; i < App.shader.presets.items.size(); i++) { + if (App.shader.presets.items[i].value == defalut_preset) { + App.shader.presets.selected = i; + App.shader.selected = i; + } + } + + trace_log("Loading default (%s) preset!", defalut_preset.c_str()); + loadPreset(); +} + +void Upscaler::setupPasses() +{ + if (m_passes.empty()) + return; + + bool complete = true; + + TextureCreateInfo texture_ci; + texture_ci.size = App.game.tex_size; + texture_ci.slot = TEXTURE_SLOT_DEFAULT; + if (m_passes[0].linear_filter) + texture_ci.filter = { GL_LINEAR, GL_LINEAR }; + m_input_texture = Context::createTexture(texture_ci); + + m_passes[0].out_size = App.game.tex_size; + glm::uvec2 vwp_size = { (uint32_t)((float)App.game.tex_size.x * App.viewport.scale.x), (uint32_t)((float)App.game.tex_size.y * App.viewport.scale.y) }; + + for (size_t i = 0; i < m_passes.size(); i++) { + auto& pass = m_passes[i]; + auto& prev = m_passes[i - (i > 0 ? 1 : 0)]; + auto& next = m_passes[i + (i < m_passes.size() - 1 ? 1 : 0)]; + const bool is_last = (i == m_passes.size() - 1); + + if (!is_last) { + if (pass.scale_type.x != ScaleType::Absolute) + pass.out_size.x = (uint32_t)((pass.scale_type.x == ScaleType::Source ? prev.out_size.x : vwp_size.x) * pass.scale_size.x); + else + pass.out_size.x = (uint32_t)pass.scale_size.x; + if (pass.scale_type.y != ScaleType::Absolute) + pass.out_size.y = (uint32_t)((pass.scale_type.y == ScaleType::Source ? prev.out_size.y : vwp_size.y) * pass.scale_size.y); + else + pass.out_size.y = (uint32_t)pass.scale_size.y; + } else + pass.out_size = vwp_size; + + if (!is_last) { + GLint filter = next.linear_filter ? GL_LINEAR : GL_NEAREST; + FrameBufferCreateInfo frambuffer_ci; + frambuffer_ci.size = pass.out_size; + frambuffer_ci.attachments = { { i + 1, {}, { filter, filter }, pass.format } }; + pass.frame_buffer = Context::createFrameBuffer(frambuffer_ci); + if (!pass.frame_buffer->isComplete()) { + complete = false; + break; + } + } + + std::vector bindings; + + const auto mvp = is_last ? glm::ortho(-App.game.tex_scale.x, App.game.tex_scale.x, -App.game.tex_scale.y, App.game.tex_scale.y) : glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f); + if (auto u = pass.getUniformPrefixed("MVP"); u != "") + pass.pipeline->setUniformMat4f(u, mvp); + if (auto u = pass.getSamplerName("Original"); u != "") { + pass.pipeline->setUniform1i(u, TEXTURE_SLOT_DEFAULT); + bindings.push_back({ BindingType::Texture, "Original", TEXTURE_SLOT_DEFAULT, &m_input_texture }); + } + if (auto u = pass.getSamplerName("Source"); u != "") { + pass.pipeline->setUniform1i(u, i == 0 ? TEXTURE_SLOT_DEFAULT : i); + if (i == 0) + bindings.push_back({ BindingType::Texture, "Source", TEXTURE_SLOT_DEFAULT, &m_input_texture }); + else + bindings.push_back({ BindingType::FBTexture, "Source", i, &prev.frame_buffer }); + } + + if (auto u = pass.getUniformPrefixed("SourceSize"); u != "") { + if (i == 0) + pass.pipeline->setUniformVec4f(u, { (float)App.game.tex_size.x, (float)App.game.tex_size.y, 1.0f / (float)App.game.tex_size.x, 1.0f / (float)App.game.tex_size.y }); + else + pass.pipeline->setUniformVec4f(u, { (float)prev.out_size.x, (float)prev.out_size.y, 1.0f / (float)prev.out_size.x, 1.0f / (float)prev.out_size.y }); + } + if (auto u = pass.getUniformPrefixed("OutputSize"); u != "") + pass.pipeline->setUniformVec4f(u, { (float)pass.out_size.x, (float)pass.out_size.y, 1.0f / (float)pass.out_size.x, 1.0f / (float)pass.out_size.y }); + if (auto u = pass.getUniformPrefixed("FinalViewportSize"); u != "") + pass.pipeline->setUniformVec4f(u, { (float)vwp_size.x, (float)vwp_size.y, 1.0f / (float)vwp_size.x, 1.0f / (float)vwp_size.y }); + + for (auto p : pass.params) { + if (auto u = pass.getUniformPrefixed(p.id); u != "") + pass.pipeline->setUniform1f(u, p.value); + } + + if (i > 0) { + for (size_t j = 0; j < i; j++) { + auto& p_pass = m_passes[j]; + const glm::vec4 out_size = { (float)p_pass.out_size.x, (float)p_pass.out_size.y, 1.0f / (float)p_pass.out_size.x, 1.0f / (float)p_pass.out_size.y }; + if (p_pass.name != "") { + if (auto u = pass.getSamplerName(p_pass.name); u != "") { + pass.pipeline->setUniform1i(u, j + 1); + bindings.push_back({ BindingType::FBTexture, u, j + 1, &p_pass.frame_buffer }); + } + if (auto u = pass.getUniformPrefixed(p_pass.name + "Size"); u != "") + pass.pipeline->setUniformVec4f(u, out_size); + } + const std::string num = std::to_string(j); + if (auto u = pass.getSamplerName("PassOutput" + num); u != "") { + pass.pipeline->setUniform1i(u, j + 1); + bindings.push_back({ BindingType::FBTexture, u, j + 1, &p_pass.frame_buffer }); + } + if (auto u = pass.getUniformPrefixed("PassOutputSize" + num); u != "") + pass.pipeline->setUniformVec4f(u, out_size); + } + } + + if (auto u = pass.getUniformPrefixed("FrameCount"); u != "") { + if (pass.pipeline->getUniformLocation(u) > -1) + pass.frame_count_uniform = u; + } + + for (auto& p : m_textures) { + if (auto u = pass.getSamplerName(p.first); u != "") { + pass.pipeline->setUniform1i(u, p.second->getSlot()); + bindings.push_back({ BindingType::Texture, u, p.second->getSlot(), &p.second }); + } + } + if (!bindings.empty()) + pass.pipeline->updateBindings(bindings); + } + + if (!complete) { + loadDefaultPreset(); + setupPasses(); + } +} + +void Upscaler::process(const std::unique_ptr& in_fbo, const glm::ivec2& vp_size, const glm::ivec2& vp_offset, const std::unique_ptr& out_fbo) +{ + Context* ctx = App.context.get(); + m_input_texture->fillFromBuffer(in_fbo); + + for (size_t i = 0; i < m_passes.size(); i++) { + const auto& pass = m_passes[i]; + const bool is_last = (i == m_passes.size() - 1); + + if (is_last) { + if (out_fbo) { + ctx->bindFrameBuffer(out_fbo, false); + ctx->setViewport(App.viewport.size); + } else { + ctx->bindDefaultFrameBuffer(); + ctx->setViewport(vp_size, vp_offset); + } + } else { + ctx->bindFrameBuffer(pass.frame_buffer, false); + ctx->setViewport(pass.out_size); + } + ctx->bindPipeline(pass.pipeline); + if (pass.frame_count_uniform != "") + pass.pipeline->setUniform1u(pass.frame_count_uniform, ctx->getFrameCount()); + ctx->drawQuad(); + } +} + +bool Upscaler::prepareShader(ShaderPass& pass, std::string shader_path) +{ + auto buffer = helpers::loadFile(shader_path); + if (!buffer.size) + return false; + + std::string shader_source((const char*)buffer.data, buffer.size); + delete[] buffer.data; + resolveInclude(shader_source, shader_path); + + uint8_t stage = 0; + std::string vert_source, frag_source; + + auto lines = helpers::strToLines(shader_source); + for (auto& line : lines) { + if (line.substr(0, 7) == "#pragma") { + helpers::trimString(line, "\t\n\v\f\r "); + auto pragma_name = line.substr(8, line.find(' ', 8) - 8); + auto pragma_value = line.substr(9 + pragma_name.length()); + + if (pragma_name == "stage") + stage = pragma_value == "vertex" ? 1 : 2; + else if (pragma_name == "name") { + pass.name = pragma_value; + pass.label += " (" + pragma_value + ")"; + } else if (pragma_name == "format") + pass.format = getFramebufferFormat(pragma_value); + else if (pragma_name == "parameter") { + std::string::iterator new_end = std::unique(pragma_value.begin(), pragma_value.end(), [](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }); + pragma_value.erase(new_end, pragma_value.end()); + std::string desc = ""; + size_t s_pos = pragma_value.find("\""); + if (s_pos != std::string::npos) { + size_t e_pos = pragma_value.rfind("\""); + if (e_pos != std::string::npos) { + desc = pragma_value.substr(s_pos, e_pos - s_pos + 1); + pragma_value.replace(s_pos, e_pos - s_pos + 1, ""); + helpers::trimString(desc, "\""); + } + } + const auto seg = helpers::splitToVector(pragma_value, ' '); + desc = desc != "" ? desc : seg[1]; + const float step = seg.size() > 5 ? std::stof(seg[5]) : 1.0f; + pass.params.push_back({ seg[0], desc, std::stof(seg[2]), std::stof(seg[3]), std::stof(seg[4]), step }); + } + continue; + } + if (stage == 0 || stage == 1) + vert_source += line + "\n"; + if (stage == 0 || stage == 2) + frag_source += line + "\n"; + } + + glslang::Result res1, res2; + try { + res1 = glslang::getGLSLCode(glslang::ShaderStage::Vertex, { App.gl_ver.x, App.gl_ver.y }, vert_source); + if (!res1.result) { + error_log("Vertex shader compile failed! %s: %s", pass.name.c_str(), res1.err_msg.c_str()); + return false; + } + res2 = glslang::getGLSLCode(glslang::ShaderStage::Fragment, { App.gl_ver.x, App.gl_ver.y }, frag_source); + if (!res2.result) { + error_log("Fragment shader compile failed! %s: %s", pass.name.c_str(), res2.err_msg.c_str()); + return false; + } + } catch (...) { + error_log("Slang to GLSL shader compile failed! %s", pass.name.c_str()); + return false; + } + res1.source = res1.source.erase(0, res1.source.find("\n") + 1); + res2.source = res2.source.erase(0, res2.source.find("\n") + 1); + std::string source = "#ifdef VERTEX\n" + res1.source + "\n#elif FRAGMENT\n" + res2.source + "\n#endif"; + + PipelineCreateInfo pipeline_ci = { pass.name }; + pipeline_ci.shader = source.c_str(); + pipeline_ci.version = App.gl_ver; + pass.pipeline = Context::createPipeline(pipeline_ci); + if (!pass.pipeline->isCompileSuccess()) + return false; + + for (const auto& p : res1.samplers) + pass.samplers.push_back(p); + for (const auto& p : res2.samplers) + pass.samplers.push_back(p); + + for (const auto& p : res1.uniforms) + pass.uniforms[p.first] = p.second; + for (const auto& p : res2.uniforms) + pass.uniforms[p.first] = p.second; + + return true; +} + +void Upscaler::resolveInclude(std::string& source, std::string file_path) +{ + bool dqm = false; + int s1 = -1, s2 = -1; + std::deque> cm_occurrences; + + for (size_t i = 0; i < source.size() - 1; i++) { + const auto c0 = source[i]; + const auto c1 = source[i + 1]; + const bool end = i + 2 == source.size(); + if (!dqm) { + if (s1 > -1 && (end || (c0 == '*' && c1 == '/'))) { + i++; + cm_occurrences.push_front({ s1, i + 1 - s1 }); + s1 = -1; + } else if (s2 > -1 && (end || c0 == '\n' || c0 == '\r')) { + cm_occurrences.push_front({ s2, i + 1 - s2 }); + s2 = -1; + } else if (s1 == -1 && s2 == -1 && c0 == '/') { + if (c1 == '*') + s1 = i; + else if (c1 == '/') + s2 = i; + } + } + if (s1 == -1 && s2 == -1 && c0 == '"') + dqm = !dqm; + } + + for (auto& p : cm_occurrences) + source.erase(p.first, p.second); + + size_t start = 0; + std::deque> inc_occurrences; + + while ((start = source.find("#include", start)) != std::string::npos) { + size_t s_pos = start + 9; + size_t e_pos = source.find("\n", s_pos); + e_pos = e_pos == std::string::npos ? source.length() : e_pos; + std::string inc_file = source.substr(s_pos, e_pos - s_pos); + + helpers::trimString(inc_file, "\t\n\v\f\r "); + inc_file.erase(std::remove(inc_file.begin(), inc_file.end(), '"'), inc_file.end()); + inc_occurrences.push_front({ start, e_pos - start, inc_file }); + start += 9; + } + + for (auto& p : inc_occurrences) { + auto inc_file = helpers::filePathFix(file_path, std::get<2>(p)); + std::string inc_file_source = ""; + auto buffer = helpers::loadFile(inc_file); + if (buffer.size) { + inc_file_source = std::string((const char*)buffer.data, buffer.size); + delete[] buffer.data; + resolveInclude(inc_file_source, inc_file); + source.replace(std::get<0>(p), std::get<1>(p), inc_file_source); + } + } +} + +std::pair Upscaler::getFramebufferFormat(const std::string& format) +{ + static const std::map> formats = { + { "R8_UNORM", { GL_R8, GL_RED } }, + { "R8_UINT", { GL_R8UI, GL_RED_INTEGER } }, + { "R8_SINT", { GL_R8I, GL_RED_INTEGER } }, + { "R8G8_UNORM", { GL_RG8, GL_RG } }, + { "R8G8_UINT", { GL_RG8UI, GL_RG_INTEGER } }, + { "R8G8_SINT", { GL_RG8I, GL_RG_INTEGER } }, + { "R8G8B8A8_UNORM", { GL_RGBA8, GL_RGBA } }, + { "R8G8B8A8_UINT", { GL_RGBA8UI, GL_RGBA_INTEGER } }, + { "R8G8B8A8_SINT", { GL_RGBA8I, GL_RGBA_INTEGER } }, + { "R8G8B8A8_SRGB", { GL_SRGB8_ALPHA8, GL_RGBA } }, + { "A2B10G10R10_UNORM_PACK32", { GL_RGB10_A2, GL_RGBA } }, + { "A2B10G10R10_UINT_PACK32", { GL_RGB10_A2UI, GL_RGBA_INTEGER } }, + { "R16_UINT", { GL_R16UI, GL_RED_INTEGER } }, + { "R16_SINT", { GL_R16I, GL_RED_INTEGER } }, + { "R16_SFLOAT", { GL_R16F, GL_RED } }, + { "R16G16_UINT", { GL_RG16UI, GL_RG_INTEGER } }, + { "R16G16_SINT", { GL_RG16I, GL_RG_INTEGER } }, + { "R16G16_SFLOAT", { GL_RG16F, GL_RG } }, + { "R16G16B16A16_UINT", { GL_RGBA16UI, GL_RGBA_INTEGER } }, + { "R16G16B16A16_SINT", { GL_RGBA16I, GL_RGBA_INTEGER } }, + { "R16G16B16A16_SFLOAT", { GL_RGBA16F, GL_RGBA } }, + { "R32_UINT", { GL_R32UI, GL_RED_INTEGER } }, + { "R32_SINT", { GL_R32I, GL_RED_INTEGER } }, + { "R32_SFLOAT", { GL_R32F, GL_RED } }, + { "R32G32_UINT", { GL_RG32UI, GL_RG_INTEGER } }, + { "R32G32_SINT", { GL_RG32I, GL_RG_INTEGER } }, + { "R32G32_SFLOAT", { GL_RG32F, GL_RG } }, + { "R32G32B32A32_UINT", { GL_RGBA32UI, GL_RGBA_INTEGER } }, + { "R32G32B32A32_SINT", { GL_RGBA32I, GL_RGBA_INTEGER } }, + { "R32G32B32A32_SFLOAT", { GL_RGBA32F, GL_RGBA } }, + }; + + if (formats.find(format) != formats.end()) + return formats.at(format); + + return { GL_RGBA8, GL_RGBA }; +} + +} \ No newline at end of file diff --git a/d2gl/src/graphic/upscaler.h b/d2gl/src/graphic/upscaler.h new file mode 100644 index 0000000..f9f5439 --- /dev/null +++ b/d2gl/src/graphic/upscaler.h @@ -0,0 +1,94 @@ +/* + D2GL: Diablo 2 LoD Glide/DDraw to OpenGL Wrapper. + Copyright (C) 2023 Bayaraa + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "pipeline.h" + +namespace d2gl { + +enum class ScaleType { + Source, + Viewport, + Absolute, +}; + +struct ShaderParam { + std::string id; + std::string desc; + float value = 0.0f; + float min = 0.0f; + float max = 0.0f; + float step = 1.0f; +}; + +struct TextureInfo { + std::string path; + bool linear = true; + bool mip_map = false; + GLint wrap_mode = GL_CLAMP_TO_EDGE; +}; + +struct ShaderPass { + std::string label; + std::string name = ""; + glm::vec<2, uint32_t> out_size = { 0, 0 }; + glm::vec<2, ScaleType> scale_type = { ScaleType::Source, ScaleType::Source }; + glm::vec2 scale_size = { 1.0f, 1.0f }; + bool linear_filter = false; + std::string frame_count_uniform = ""; + + std::vector params; + std::unique_ptr pipeline; + std::pair format = { GL_RGBA8, GL_RGBA }; + std::unique_ptr frame_buffer; + std::vector samplers; + std::unordered_map uniforms; + + inline std::string getSamplerName(const std::string& sampler) const { return std::find(samplers.begin(), samplers.end(), sampler) != samplers.end() ? sampler : ""; } + inline std::string getUniformPrefixed(const std::string& uniform) const { return uniforms.find(uniform) != uniforms.end() ? uniforms.at(uniform) + "." + uniform : ""; } +}; + +class Upscaler { + std::vector m_passes = {}; + std::unique_ptr m_input_texture; + std::unordered_map> m_textures; + + Upscaler(); + ~Upscaler() = default; + +public: + static Upscaler& Instance() + { + static Upscaler instance; + return instance; + } + + bool loadPreset(); + void loadDefaultPreset(); + void setupPasses(); + void process(const std::unique_ptr& in_fbo, const glm::ivec2& vp_size, const glm::ivec2& vp_offset, const std::unique_ptr& out_fbo = nullptr); + +private: + bool prepareShader(ShaderPass& pass, std::string shader_path); + + static void resolveInclude(std::string& source, std::string file_path); + static std::pair getFramebufferFormat(const std::string& format); +}; + +} \ No newline at end of file diff --git a/d2gl/src/helpers.cpp b/d2gl/src/helpers.cpp index 3bce14d..d0b9fd3 100644 --- a/d2gl/src/helpers.cpp +++ b/d2gl/src/helpers.cpp @@ -40,6 +40,30 @@ bool fileExists(std::string file_path) return std::filesystem::exists(file_path) && std::filesystem::is_regular_file(file_path); } +std::string filePathFix(std::string parent_file_path, std::string file_path) +{ + helpers::replaceAll(parent_file_path, "/", "\\"); + parent_file_path = parent_file_path.substr(0, parent_file_path.rfind('\\')); + + helpers::replaceAll(file_path, "/", "\\"); + if (file_path.find(".\\") == 0) + file_path = file_path.substr(2); + + size_t occurence_pos = 0; + while (file_path.find("..\\", occurence_pos) != std::string::npos) + occurence_pos += 3; + + if (occurence_pos) { + file_path = file_path.substr(occurence_pos); + for (size_t i = 0; i < occurence_pos / 3; i++) { + size_t pos = parent_file_path.rfind("\\"); + if (pos != std::string::npos) + parent_file_path = parent_file_path.substr(0, pos); + } + } + return parent_file_path + "\\" + file_path; +} + std::vector strToLines(const std::string& str) { std::vector result; @@ -92,6 +116,12 @@ void strToLower(std::string& str) std::transform(str.begin(), str.end(), str.begin(), [](uint8_t c) { return std::tolower(c); }); } +void trimString(std::string& str, const char* chars) +{ + str.erase(0, str.find_first_not_of(chars)); + str.erase(str.find_last_not_of(chars) + 1); +} + std::string getLangString(bool path) { if (path) { @@ -373,6 +403,7 @@ ImageData loadImage(const std::string& file_path, bool flipped) if (buffer.size) { stbi_set_flip_vertically_on_load(flipped); image.data = stbi_load_from_memory(buffer.data, buffer.size, &image.width, &image.height, &image.bit, 4); + delete[] buffer.data; } return image; diff --git a/d2gl/src/helpers.h b/d2gl/src/helpers.h index 2ce1bbd..f6ed654 100644 --- a/d2gl/src/helpers.h +++ b/d2gl/src/helpers.h @@ -46,6 +46,7 @@ namespace d2gl::helpers { std::string getCurrentDir(); bool fileExists(std::string file_path); +std::string filePathFix(std::string parent_file_path, std::string file_path); std::vector strToLines(const std::string& str); std::vector strToLines(const std::wstring& str); @@ -53,6 +54,7 @@ std::vector splitToVector(const std::string& str, char delimeter = void replaceAll(std::string& str, const std::string& from, const std::string& to); void strToLower(std::string& str); +void trimString(std::string& str, const char* chars = " "); std::string getLangString(bool path = false); diff --git a/d2gl/src/log.cpp b/d2gl/src/log.cpp index 7555275..2812f72 100644 --- a/d2gl/src/log.cpp +++ b/d2gl/src/log.cpp @@ -33,7 +33,7 @@ void logInit() time_t now = time(0); tm gmt_time; localtime_s(&gmt_time, &now); - fprintf(log_file, "== D2GL logging started. (%d/%d/%d) ==\n\n", gmt_time.tm_year + 1900, gmt_time.tm_mon + 1, gmt_time.tm_mday); + fprintf(log_file, "== D2GL v%s logging started. (%d/%d/%d) ==\n\n", App.version_str.c_str(), gmt_time.tm_year + 1900, gmt_time.tm_mon + 1, gmt_time.tm_mday); logFileClose(); } } diff --git a/d2gl/src/modules/hd_cursor.cpp b/d2gl/src/modules/hd_cursor.cpp index aa830aa..9a57170 100644 --- a/d2gl/src/modules/hd_cursor.cpp +++ b/d2gl/src/modules/hd_cursor.cpp @@ -51,8 +51,7 @@ HDCursor::HDCursor() texture_ci.size = { 128, 128 }; texture_ci.layer_count = 50; texture_ci.slot = TEXTURE_SLOT_CURSOR; - texture_ci.min_filter = GL_LINEAR; - texture_ci.mag_filter = GL_LINEAR; + texture_ci.filter = { GL_LINEAR, GL_LINEAR }; m_texture = Context::createTexture(texture_ci); m_hand_cursor = std::make_unique(m_texture, "assets\\textures\\cursor\\hand.png", 19, glm::vec2(1.0f, 6.0f)); diff --git a/d2gl/src/modules/hd_text.cpp b/d2gl/src/modules/hd_text.cpp index f62f479..801af90 100644 --- a/d2gl/src/modules/hd_text.cpp +++ b/d2gl/src/modules/hd_text.cpp @@ -1,4 +1,4 @@ -/* +/* D2GL: Diablo 2 LoD Glide/DDraw to OpenGL Wrapper. Copyright (C) 2023 Bayaraa @@ -41,13 +41,13 @@ HDText::HDText() if (buffer.size) { std::string data((const char*)buffer.data, buffer.size); auto lines = helpers::strToLines(data); + delete[] buffer.data; TextureCreateInfo texture_ci; texture_ci.layer_count = 1; texture_ci.size = { 1024, 1024 }; texture_ci.slot = TEXTURE_SLOT_FONTS; - texture_ci.min_filter = GL_LINEAR; - texture_ci.mag_filter = GL_LINEAR; + texture_ci.filter = { GL_LINEAR, GL_LINEAR }; static std::unordered_map glyph_sets; std::vector> info_list; @@ -57,7 +57,7 @@ HDText::HDText() auto info = helpers::splitToVector(line, '|'); if (info.size() > 9) { - if (glyph_sets.find(info[9]) == glyph_sets.end()) { + if (glyph_sets.find(info[1]) == glyph_sets.end()) { auto buffer2 = helpers::loadFile("assets\\atlases\\" + info[1] + "\\data.csv"); if (buffer2.size) { auto pos = (buffer2.data + (buffer2.size - 5)); @@ -75,7 +75,7 @@ HDText::HDText() } static std::unique_ptr texture = Context::createTexture(texture_ci); - auto symbol_set = new GlyphSet(texture.get(), "NotoSymbol"); + static auto symbol_set = new GlyphSet(texture.get(), "NotoSymbol"); for (auto& info : info_list) { const auto name = info[1]; @@ -86,15 +86,11 @@ HDText::HDText() bool bordered = (id == 2 || id == 3 || id == 7 || id == 18); wchar_t color = g_initial_colors.find(id) != g_initial_colors.end() ? g_initial_colors.at(id) : 0; const auto offset = glm::vec2(std::stof(info[7]), std::stof(info[8])); - float font_size = std::stof(info[2]) * App.hd_text.scale.value; - float line_height = std::stof(info[5]) * App.hd_text.scale.value; - FontCreateInfo font_ci = { name, font_size, std::stof(info[3]), std::stof(info[4]), line_height, std::stof(info[6]), offset, std::stof(info[9]), color, bordered }; + FontCreateInfo font_ci = { name, std::stof(info[2]), std::stof(info[3]), std::stof(info[4]), std::stof(info[5]), std::stof(info[6]), offset, std::stof(info[9]), color, bordered }; m_fonts[id] = std::make_unique(glyph_sets[name], font_ci); } - delete[] buffer.data; - if (m_lang_id != LANG_ENG && m_lang_id != LANG_DEF) { if (m_lang_id != LANG_POR && m_lang_id != LANG_SIN && m_lang_id != LANG_RUS) { for (size_t i = 0; i < g_options_texts.size(); i++) @@ -126,7 +122,7 @@ HDText::HDText() App.hdt.fonts.items.push_back({ "17: Level/Class text on char selection screen (Custom)", 17 }); App.hdt.fonts.items.push_back({ "18: Level Entry text (Custom)", 18 }); App.hdt.fonts.items.push_back({ "19: Minimap first line text/clock/fps counter (Custom)", 19 }); - App.hdt.fonts.items.push_back({ "20: Unused: For future reference (Custom)", 20 }); + App.hdt.fonts.items.push_back({ "20: Monster resistances text on hp bar (Custom)", 20 }); App.hdt.fonts.items.push_back({ "21: Unused: For future reference (Custom)", 21 }); App.hdt.fonts.items.push_back({ "22: Unused: For future reference (Custom)", 22 }); getFont(0)->getMetrics(); @@ -820,8 +816,8 @@ void HDText::drawMonsterHealthBar(d2::UnitAny* unit) if (!name) return; - const auto hp = d2::getUnitStat(unit, 6); - const auto max_hp = d2::getUnitStat(unit, 7); + const auto hp = d2::getUnitStat(unit, STAT_HP); + const auto max_hp = d2::getUnitStat(unit, STAT_MAXHP); const auto type = d2::getMonsterType(unit); const auto font = getFont(1); @@ -838,11 +834,11 @@ void HDText::drawMonsterHealthBar(d2::UnitAny* unit) const auto text_size = font->getTextSize(name); float hp_percent = (float)hp / (float)max_hp; - glm::vec2 bar_size = { 140.0f, 18.0f }; + glm::vec2 bar_size = { 160.0f, 18.0f }; if (text_size.x + 40.0f > bar_size.x) bar_size.x = text_size.x + 40.0f; - glm::vec2 bar_pos = { center - bar_size.x / 2, 18.0f }; + glm::vec2 bar_pos = { center - bar_size.x / 2, d2::isLangCJK(m_lang_id) ? 18.0f : 20.0f }; m_object_bg->setFlags(2); m_object_bg->setPosition(bar_pos); @@ -867,9 +863,34 @@ void HDText::drawMonsterHealthBar(d2::UnitAny* unit) if (hp == 0) text_color = L'\x31'; - glm::vec2 text_pos = { center - text_size.x / 2, 19.3f + 14.5f }; + glm::vec2 text_pos = { center - text_size.x / 2, bar_pos.y + 15.8f }; font->drawText(name, text_pos, g_text_colors.at(text_color)); m_hovered_unit.color = 0; + + if (App.show_monster_res) { + const auto s1 = d2::getUnitStat(unit, STAT_DMGREDUCTIONPCT); + const wchar_t* i1 = s1 >= 100 ? L"⛦" : L""; + const auto s2 = d2::getUnitStat(unit, STAT_MAGICDMGREDUCTIONPCT); + const wchar_t* i2 = s2 >= 100 ? L"⛦" : L""; + const auto s3 = d2::getUnitStat(unit, STAT_FIRERESIST); + const wchar_t* i3 = s3 >= 100 ? L"⛦" : L""; + const auto s4 = d2::getUnitStat(unit, STAT_LIGHTNINGRESIST); + const wchar_t* i4 = s4 >= 100 ? L"⛦" : L""; + const auto s5 = d2::getUnitStat(unit, STAT_COLDRESIST); + const wchar_t* i5 = s5 >= 100 ? L"⛦" : L""; + const auto s6 = d2::getUnitStat(unit, STAT_POISONRESIST); + const wchar_t* i6 = s6 >= 100 ? L"⛦" : L""; + + static wchar_t res_str[100]; + swprintf_s(res_str, L"ÿc\x34%s%d ÿc\x03⌁ ÿc\x38%s%d ÿc\x03⌁ ÿc\x31%s%d ÿc\x03⌁ ÿc\x39%s%d ÿc\x03⌁ ÿc\x33%s%d ÿc\x03⌁ ÿc\x32%s%d", i1, s1, i2, s2, i3, s3, i4, s4, i5, s5, i6, s6); + + const auto font = getFont(20); + font->setShadow(1); + font->setMasking(false); + + const auto text_size = font->getTextSize(res_str); + font->drawText(res_str, { center - text_size.x / 2.0f, bar_pos.y - 3.0f }, g_text_colors.at(16)); + } } void HDText::drawPlayerHealthBar(d2::UnitAny* unit) @@ -937,14 +958,20 @@ void HDText::drawFpsCounter() d2::setTextSizeHooked(old_size); } -void HDText::drawItemQuantity(int x, int y) +void HDText::drawItemQuantity(bool draw, int x, int y) { - if (!App.show_item_quantity || !d2::currently_drawing_item) + if (!App.show_item_quantity || App.game.screen != GameScreen::InGame || !d2::currently_drawing_item) return; + static glm::ivec2 item_pos = { 0, 0 }; + if (!draw) { + item_pos = { x, y }; + return; + } + const auto item = d2::currently_drawing_item; if (item->dwType == d2::UnitType::Item && d2::getItemLocation(item) != 0xFF) { - if (const auto quantity = d2::getUnitStat(item, 70)) { + if (const auto quantity = d2::getUnitStat(item, STAT_ITEMQUANTITY)) { static wchar_t str[10] = { 0 }; swprintf_s(str, L"%d", quantity); @@ -956,7 +983,7 @@ void HDText::drawItemQuantity(int x, int y) d2::getFramedTextSizeHooked(str, &width, &height); glm::vec2 size = { (float)(width + 10), (float)(height + 2) }; - glm::vec2 pos = { (float)(x - 5 + 3), (float)(y - 1 - height - 2) }; + glm::vec2 pos = { (float)(item_pos.x - 5 + 3), (float)(item_pos.y - 1 - height - 4) }; bg->setFlags(6, 0, 0, 1); bg->setPosition(pos); @@ -965,10 +992,17 @@ void HDText::drawItemQuantity(int x, int y) bg->setExtra({ 0.4f, 0.6f }); App.context->pushObject(bg); } - d2::drawNormalTextHooked(str, x + 3, y - 2, 0, 0); + d2::drawNormalTextHooked(str, item_pos.x + 3, item_pos.y - 4, 0, 0); d2::setTextSizeHooked(old_size); } } + d2::currently_drawing_item = nullptr; +} + +void HDText::updateFontSize() +{ + for (auto& font : m_fonts) + font.second->setSize(); } #ifdef _HDTEXT @@ -982,15 +1016,15 @@ void HDText::showSampleText() const auto old_size = HDText::Instance().getTextSize(); d2::drawSolidRectEx(40, 40, App.game.size.x - 40, App.game.size.y - 100, 1, 2); if (id <= 13) { - bool old_val = App.hd_text; - App.hd_text = false; + bool old_val = App.hd_text.active; + App.hd_text.active = false; d2::setTextSize(id); d2::drawNormalText(texts.txt1, 60, 140, 0, 0); d2::setTextSize(id); d2::drawNormalText(texts.txt2, 60, 260, 0, 0); d2::setTextSize(id); d2::drawNormalText(texts.txt3, 60, 460, 0, 0); - App.hd_text = old_val; + App.hd_text.active = old_val; } d2::drawSolidRectEx(60, 60, App.game.size.x - 60, App.game.size.y - 140, 1, 1); diff --git a/d2gl/src/modules/hd_text.h b/d2gl/src/modules/hd_text.h index c05ccda..870f666 100644 --- a/d2gl/src/modules/hd_text.h +++ b/d2gl/src/modules/hd_text.h @@ -69,6 +69,7 @@ class HDText { const uint32_t m_monster_hp = 0x56110BDD; HDText(); + ~HDText() = default; public: static HDText& Instance() @@ -82,6 +83,7 @@ class HDText { void reset(); void update(); + void updateFontSize(); bool drawText(const wchar_t* str, int x, int y, uint32_t color, uint32_t centered); bool drawFramedText(const wchar_t* str, int x, int y, uint32_t color, uint32_t centered); @@ -108,7 +110,7 @@ class HDText { void drawEntryText(); static void drawFpsCounter(); - static void drawItemQuantity(int x, int y); + static void drawItemQuantity(bool draw, int x = 0, int y = 0); private: void drawMonsterHealthBar(d2::UnitAny* unit); diff --git a/d2gl/src/modules/hd_text/font.cpp b/d2gl/src/modules/hd_text/font.cpp index 7de5fbf..fcd40d3 100644 --- a/d2gl/src/modules/hd_text/font.cpp +++ b/d2gl/src/modules/hd_text/font.cpp @@ -23,10 +23,10 @@ namespace d2gl { Font::Font(GlyphSet* glyph_set, const FontCreateInfo& font_ci) - : m_glyph_set(glyph_set), m_name(font_ci.name), m_weight(font_ci.weight), m_letter_spacing(font_ci.letter_spacing), m_line_height(font_ci.line_height), + : m_glyph_set(glyph_set), m_name(font_ci.name), m_size(font_ci.size), m_weight(font_ci.weight), m_letter_spacing(font_ci.letter_spacing), m_line_height(font_ci.line_height), m_shadow_intensity(font_ci.shadow_intensity), m_offset(font_ci.offset), m_symbol_offset(font_ci.symbol_offset), m_color(font_ci.color), m_bordered(font_ci.bordered) { - setSize(font_ci.size); + setSize(); m_object = std::make_unique(); } @@ -69,7 +69,7 @@ glm::vec2 Font::getTextSize(const wchar_t* str, const int max_chars) m_line_count = line_num + 1; m_line_width[line_num] = advance; m_text_size.x = glm::max(m_text_size.x, advance); - m_text_size.y += line_height - (line_height - m_size); + m_text_size.y += line_height - (line_height - m_font_size); return m_text_size; } @@ -84,7 +84,9 @@ void Font::drawText(const wchar_t* str, glm::vec2 pos, uint32_t color, bool fram if (framed) { offset.x = text_offset.x = 0.0f; offset.y += (float)m_line_count * line_height - line_height; - } + } else + offset.y += (m_font_size - m_size) / 2.0f; + if (m_align == TextAlign::Right) offset.x += m_text_size.x - m_line_width[0]; else if (m_align == TextAlign::Center) @@ -139,7 +141,7 @@ float Font::drawChar(wchar_t c, glm::vec2 pos, uint32_t color) glm::vec2 object_pos = pos + glyph->offset * m_scale; float weight = m_weight; if (m_glyph_set->isSymbol()) { - object_pos.y += m_size * m_symbol_offset; + object_pos.y += m_font_size * m_symbol_offset; weight = 1.0f + ((m_weight - 1.0f) * 0.5f); } @@ -167,7 +169,7 @@ float Font::drawChar(wchar_t c, glm::vec2 pos, uint32_t color) #ifdef _HDTEXT void Font::updateMetrics() { - setSize(App.hdt.size.value); + m_size = App.hdt.size.value; m_weight = App.hdt.weight.value; m_letter_spacing = App.hdt.letter_spacing.value; m_line_height = App.hdt.line_height.value; @@ -175,6 +177,7 @@ void Font::updateMetrics() m_offset.x = App.hdt.offset_x.value; m_offset.y = App.hdt.offset_y.value; m_symbol_offset = App.hdt.symbol_offset.value; + setSize(); } void Font::getMetrics() diff --git a/d2gl/src/modules/hd_text/font.h b/d2gl/src/modules/hd_text/font.h index b85c206..3828a98 100644 --- a/d2gl/src/modules/hd_text/font.h +++ b/d2gl/src/modules/hd_text/font.h @@ -45,6 +45,7 @@ class Font { bool m_bordered = false; float m_size = 10.0f; + float m_font_size = 10.0f; float m_weight = 1.0f; float m_line_height = 1.0f; float m_letter_spacing = 0.0f; @@ -66,17 +67,17 @@ class Font { Font(GlyphSet* glyph_set, const FontCreateInfo& font_ci); ~Font() = default; - inline void setSize(float size) { m_size = size / App.hd_text.scale.value, m_scale = size / 32.0f, m_smoothness = size; } + inline void setSize() { m_font_size = m_size * App.hd_text.scale.value, m_scale = m_font_size / 32.0f, m_smoothness = m_font_size; } inline void setAlign(TextAlign align) { m_align = align; } inline void setShadow(uint8_t level = 0) { m_shadow_level = level; } inline void setMasking(bool masking) { m_masking = masking; } inline wchar_t getColor() { return m_color; } - inline float getFontSize() { return m_size; } + inline float getFontSize() { return m_font_size; } inline float getWeight() { return m_weight; } - inline float getLineHeight() { return m_size * m_line_height * App.hd_text.scale.value; } - inline float getLetterSpacing() { return m_size * m_letter_spacing; } - inline glm::vec2 getTextOffset() { return m_size * m_offset; } + inline float getLineHeight() { return m_font_size * m_line_height; } + inline float getLetterSpacing() { return m_font_size * m_letter_spacing; } + inline glm::vec2 getTextOffset() { return m_font_size * m_offset; } inline int getLineCount() { return m_line_count; } glm::vec2 getTextSize(const wchar_t* str, const int max_chars = 0); diff --git a/d2gl/src/modules/hd_text/glyph_set.cpp b/d2gl/src/modules/hd_text/glyph_set.cpp index 53e2dfe..9f053fa 100644 --- a/d2gl/src/modules/hd_text/glyph_set.cpp +++ b/d2gl/src/modules/hd_text/glyph_set.cpp @@ -33,6 +33,8 @@ GlyphSet::GlyphSet(Texture* texture, const std::string& name, GlyphSet* symbol_s uint32_t start_layer = 0; std::string data((const char*)buffer.data, buffer.size); auto lines = helpers::strToLines(data); + delete[] buffer.data; + for (auto& line : lines) { auto cols = helpers::splitToVector(line); @@ -55,8 +57,6 @@ GlyphSet::GlyphSet(Texture* texture, const std::string& name, GlyphSet* symbol_s m_glyphes[cc].tex_id = start_layer; m_glyphes[cc].tex_coord = coords / 1024.0f; } - - delete[] buffer.data; } const Glyph* GlyphSet::getGlyph(wchar_t c) diff --git a/d2gl/src/option/ini.cpp b/d2gl/src/option/ini.cpp index 06d5a2e..4fe0508 100644 --- a/d2gl/src/option/ini.cpp +++ b/d2gl/src/option/ini.cpp @@ -139,6 +139,8 @@ void saveIni() "; Window position.\n" "window_posx=%d\n" "window_posy=%d\n\n" + "; Unlock Cursor (cursor will not locked within window).\n" + "unlock_cursor=%s\n\n" "; Auto minimize when lose focus while in fullscreen.\n" "auto_minimize=%s\n\n" "; Dark style window title bar.\n" @@ -146,7 +148,7 @@ void saveIni() "; Vertical synchronization.\n" "; Game fps adapt screen refresh rate (might have input lag).\n" "vsync=%s\n\n" - "; Max Foreground FPS.\n" + "; Max Foreground FPS (if vsync is on this will be ignored).\n" "; Limit maximum fps when game window is focused(active) (vsync must be disabled).\n" "foreground_fps=%s\n" "foreground_fps_value=%d\n\n" @@ -162,6 +164,7 @@ void saveIni() boolString(App.window.centered), App.window.position.x, App.window.position.y, + boolString(App.cursor.unlock), boolString(App.window.auto_minimize), boolString(App.window.dark_mode), boolString(App.vsync), @@ -171,19 +174,11 @@ void saveIni() App.background_fps.range.value); out_file << buf; - std::string shader_str = ""; - for (size_t i = 0; i < App.shader.items.size(); i++) { - char label[100] = { 0 }; - sprintf_s(label, "; %2d: %s", i, App.shader.items[i].name.c_str()); - shader_str += std::string(label) + "\n"; - } - static const char* graphic_setting = "[Graphic]\n\n" "; Upscale shader.\n" - "; Set one of following shaders.\n" - "%s" - "shader=%d\n\n" + "; RetroArch's slang shader preset files (.slangp).\n" + "shader_preset=%d\n\n" "; Color grading (LUT) (only available in glide mode).\n" "; Set one of 1-%d predefined luts. 0 = game default.\n" "lut=%d\n\n" @@ -192,8 +187,9 @@ void saveIni() "sharpen_strength=%.3f\n" "sharpen_clamp=%.3f\n" "sharpen_radius=%.3f\n\n" - "; Fast approximate anti-aliasing.\n" - "fxaa=%s\n\n" + "; Fast approximate anti-aliasing (preset: 0-2).\n" + "fxaa=%s\n" + "fxaa_preset=%d\n\n" "; Bloom effect.\n" "bloom=%s\n" "bloom_exposure=%.3f\n" @@ -203,15 +199,15 @@ void saveIni() "stretched_vertical=%s\n\n\n"; sprintf_s(buf, graphic_setting, - shader_str.c_str(), - App.shader.selected, + App.shader.preset.c_str(), App.lut.items.size() - 1, App.lut.selected, boolString(App.sharpen.active), App.sharpen.strength.value, App.sharpen.clamp.value, App.sharpen.radius.value, - boolString(App.fxaa), + boolString(App.fxaa.active), + App.fxaa.presets.selected, boolString(App.bloom.active), App.bloom.exposure.value, App.bloom.gamma.value, @@ -224,8 +220,8 @@ void saveIni() "; HD cursor in game & menu screen.\n" "hd_cursor=%s\n\n" "; HD in game text.\n" - "hd_text=%s\n\n" - "hd_text_scale=%.2f\n\n" + "hd_text=%s\n" + "hd_text_scale=%.3f\n\n" //"; HD life & mana orbs.\n" //"hd_orbs=%s\n" //"hd_orbs_centered=%s\n\n" @@ -242,10 +238,10 @@ void saveIni() "no_pickup=%s\n\n" "; Show item quantity on bottom left corner of icon.\n" "show_item_quantity=%s\n\n" + "; Show monster resistances on hp bar.\n" + "show_monster_res=%s\n\n" "; Show FPS Counter (bottom center).\n" - "show_fps=%s\n\n" - "; Unlock Cursor (cursor will not locked within window).\n" - "unlock_cursor=%s\n\n\n"; + "show_fps=%s\n\n\n"; sprintf_s(buf, feature_setting, boolString(App.hd_cursor), @@ -261,8 +257,8 @@ void saveIni() boolString(App.skip_intro), boolString(App.no_pickup), boolString(App.show_item_quantity), - boolString(App.show_fps), - boolString(App.cursor.unlock)); + boolString(App.show_monster_res), + boolString(App.show_fps)); out_file << buf; static const char* other_setting = @@ -281,8 +277,8 @@ void saveIni() "load_dlls_late=%s\n"; sprintf_s(buf, other_setting, - App.gl_ver_major, - App.gl_ver_minor, + App.gl_ver.x, + App.gl_ver.y, boolString(App.use_compute_shader), App.frame_latency, App.dlls_early.c_str(), @@ -302,9 +298,6 @@ void loadIni() GetSystemMetrics(SM_CYVIRTUALSCREEN), }; - for (auto& shader : g_shader_upscale) - App.shader.items.push_back({ shader.name }); - App.lut.items.push_back({ "Game Default" }); for (int i = 1; i <= 14; i++) { char label[50] = { 0 }; @@ -317,6 +310,7 @@ void loadIni() App.window.auto_minimize = getBool("Screen", "auto_minimize", App.window.auto_minimize); App.window.dark_mode = getBool("Screen", "dark_mode", App.window.dark_mode); App.vsync = getBool("Screen", "vsync", App.vsync); + App.cursor.unlock = getBool("Screen", "unlock_cursor", App.cursor.unlock); App.window.size.x = getInt("Screen", "window_width", App.window.size.x, 800, App.desktop_resolution.z); App.window.size.y = getInt("Screen", "window_height", App.window.size.y, 600, App.desktop_resolution.w); @@ -331,9 +325,10 @@ void loadIni() App.background_fps.active = getBool("Screen", "background_fps", App.background_fps.active); App.background_fps.range.value = getInt("Screen", "background_fps_value", App.background_fps.range.value, App.background_fps.range.min, App.background_fps.range.max); - App.shader.selected = getInt("Graphic", "shader", App.shader.selected, 0, App.shader.items.size() - 1); + App.shader.preset = getString("Graphic", "shader_preset", App.shader.preset); App.lut.selected = getInt("Graphic", "lut", App.lut.selected, 0, App.lut.items.size() - 1); - App.fxaa = getBool("Graphic", "fxaa", App.fxaa); + App.fxaa.active = getBool("Graphic", "fxaa", App.fxaa.active); + App.fxaa.presets.selected = getInt("Graphic", "fxaa_preset", App.fxaa.presets.selected, 0, 2); App.sharpen.active = getBool("Graphic", "sharpen", App.sharpen.active); App.sharpen.strength.value = getFloat("Graphic", "sharpen_strength", App.sharpen.strength); @@ -349,7 +344,7 @@ void loadIni() App.hd_cursor = getBool("Feature", "hd_cursor", App.hd_cursor); App.hd_text.active = getBool("Feature", "hd_text", App.hd_text.active); - App.hd_text.scale.value = getFloat("Feature", "hd_text_scale", App.hd_text.scale); + App.hd_text.scale.value = ISHDTEXT() ? 1.0f : getFloat("Feature", "hd_text_scale", App.hd_text.scale); // App.hd_orbs.active = getBool("Feature", "hd_orbs", App.hd_orbs.active); // App.hd_orbs.centered = getBool("Feature", "hd_orbs_centered", App.hd_orbs.centered); @@ -363,13 +358,12 @@ void loadIni() App.skip_intro = getBool("Feature", "skip_intro", App.skip_intro); App.no_pickup = getBool("Feature", "no_pickup", App.no_pickup); App.show_item_quantity = getBool("Feature", "show_item_quantity", App.show_item_quantity); + App.show_monster_res = getBool("Feature", "show_monster_res", App.show_monster_res); App.show_fps = getBool("Feature", "show_fps", App.show_fps); - App.cursor.unlock = getBool("Feature", "unlock_cursor", App.cursor.unlock); - App.gl_ver_major = getInt("Other", "gl_ver_major", App.gl_ver_major, 3, 4); - App.gl_ver_minor = getInt("Other", "gl_ver_minor", App.gl_ver_minor, 0, 6); - if (App.gl_ver_major == 3) - App.gl_ver_minor = 3; + App.gl_ver.x = getInt("Other", "gl_ver_major", App.gl_ver.x, 3, 4); + App.gl_ver.y = getInt("Other", "gl_ver_minor", App.gl_ver.y, 0, 6); + App.gl_ver.y = App.gl_ver.x == 3 ? 3 : App.gl_ver.y; App.use_compute_shader = getBool("Other", "use_compute_shader", App.use_compute_shader); App.frame_latency = getInt("Other", "frame_latency", App.frame_latency, 1, 5); diff --git a/d2gl/src/option/menu.cpp b/d2gl/src/option/menu.cpp index a4a476d..6ff0710 100644 --- a/d2gl/src/option/menu.cpp +++ b/d2gl/src/option/menu.cpp @@ -40,6 +40,10 @@ namespace d2gl::option { static type opt_##id = b##.value; \ if (drawSlider(#id, a, &b, c, d, &opt_##id)) +#define checkChanged(x) \ + if (!changed && x) \ + changed = true + Menu::Menu() { m_colors[Color::Default] = ImColor(199, 179, 119); @@ -108,7 +112,7 @@ Menu::Menu() m_fonts[12] = font2.size ? io.Fonts->AddFontFromMemoryTTF((void*)font2.data, font2.size, 12.0f) : io.Fonts->Fonts[0]; App.menu_title += (ISGLIDE3X() ? " (Glide / " : " (DDraw / "); - App.menu_title += "OpenGL: " + App.gl_version + " / D2LoD: " + helpers::getVersionString() + " / " + helpers::getLangString() + ")"; + App.menu_title += "OpenGL: " + App.gl_ver_str + " / D2LoD: " + helpers::getVersionString() + " / " + helpers::getLangString() + ")"; } void Menu::toggle(bool force) @@ -120,6 +124,7 @@ void Menu::toggle(bool force) m_options.window = App.window; m_options.foreground_fps = App.foreground_fps; m_options.background_fps = App.background_fps; + m_options.unlock_cursor = App.cursor.unlock; m_closing = false; } @@ -177,90 +182,116 @@ void Menu::draw() ImGui::SetCursorPos({ 530.0f, 74.0f }); ImGui::PushFont(m_fonts[14]); ImGui::PushStyleColor(ImGuiCol_Text, m_colors[Color::Gray]); - ImGui::Text(App.version_str.c_str()); + ImGui::Text("D2GL v%s by Bayaraa.", App.version_str.c_str()); ImGui::PopStyleColor(); ImGui::PopFont(); // ImGui::SetTabItemClosed("Screen"); if (tabBegin("Screen", 0, &active_tab)) { + bool changed = m_options.pos_changed; childBegin("##w1", true, true); drawCheckbox_m("Fullscreen", m_options.window.fullscreen, "Game will run in windowed mode if unchecked.", fullscreen); + checkChanged(m_options.window.fullscreen != App.window.fullscreen); drawSeparator(); ImGui::BeginDisabled(m_options.window.fullscreen); - drawCombo_m("Window Size", App.resolutions, "Select window size.", "", 17, resolutions); - ImGui::Dummy({ 0.0f, 4.0f }); + drawCombo_m("Window Size", App.resolutions, "", false, 17, resolutions); + checkChanged(App.resolutions.items[App.resolutions.selected].value != m_options.window.size_save); + ImGui::Dummy({ 0.0f, 1.0f }); ImGui::BeginDisabled(App.resolutions.selected); drawInput2("##ws", "Input custom width & height. (min: 800 x 600)", (glm::ivec2*)(&m_options.window.size_save), { 800, 600 }, { App.desktop_resolution.z, App.desktop_resolution.w }); + checkChanged(!App.resolutions.selected && App.window.size != m_options.window.size_save); ImGui::EndDisabled(); drawSeparator(); drawCheckbox_m("Centered Window", m_options.window.centered, "Make window centered to desktop screen.", centered_window); - ImGui::Dummy({ 0.0f, 4.0f }); + checkChanged(m_options.window.centered != App.window.centered); + ImGui::Dummy({ 0.0f, 2.0f }); ImGui::BeginDisabled(m_options.window.centered); drawInput2("##wp", "Window position from top left corner.", &m_options.window.position, { App.desktop_resolution.x, App.desktop_resolution.y }, { App.desktop_resolution.z, App.desktop_resolution.w }); + checkChanged(!m_options.window.centered && App.window.position != m_options.window.position); ImGui::EndDisabled(); ImGui::EndDisabled(); + drawSeparator(); + drawCheckbox_m("Unlock Cursor", m_options.unlock_cursor, "Cursor will not locked within window.", unlock_cursor); + checkChanged(m_options.unlock_cursor != App.cursor.unlock); childSeparator("##w2", true); drawCheckbox_m("V-Sync", m_options.vsync, "Vertical Synchronization.", vsync); + checkChanged(m_options.vsync != App.vsync); drawSeparator(); ImGui::BeginDisabled(m_options.vsync); drawCheckbox_m("Max Foreground FPS", m_options.foreground_fps.active, "", foreground_fps); + checkChanged(!m_options.vsync && m_options.foreground_fps.active != App.foreground_fps.active); ImGui::BeginDisabled(!m_options.foreground_fps.active); drawSlider_m(int, "", m_options.foreground_fps.range, "%d", "Max fps when game window is active.", foreground_fps_val); + checkChanged(!m_options.vsync && m_options.foreground_fps.active && m_options.foreground_fps.range.value != App.foreground_fps.range.value); ImGui::EndDisabled(); ImGui::EndDisabled(); drawSeparator(); drawCheckbox_m("Max Background FPS", m_options.background_fps.active, "", background_fps); + checkChanged(m_options.background_fps.active != App.background_fps.active); ImGui::BeginDisabled(!m_options.background_fps.active); drawSlider_m(int, "", m_options.background_fps.range, "%d", "Max fps when game window is in inactive.", background_fps_val); + checkChanged(m_options.background_fps.active && m_options.background_fps.range.value != App.background_fps.range.value); ImGui::EndDisabled(); drawSeparator(); drawCheckbox_m("Auto Minimize", m_options.window.auto_minimize, "Auto minimize when lose focus while in fullscreen.", auto_minimize); + checkChanged(m_options.window.auto_minimize != App.window.auto_minimize); drawSeparator(); drawCheckbox_m("Dark Mode", m_options.window.dark_mode, "Dark window title bar. Affect on next launch.", dark_mode); + checkChanged(m_options.window.dark_mode != App.window.dark_mode); childEnd(); - if (drawNav("Apply Changes")) { - if (App.resolutions.selected) { - const auto val = App.resolutions.items[App.resolutions.selected].value; - m_options.window.size_save = val; - } + ImGui::BeginDisabled(!changed); + if (drawNav("Apply Changes")) { + if (App.resolutions.selected) { + const auto val = App.resolutions.items[App.resolutions.selected].value; + m_options.window.size_save = val; + } - if (App.window.size != m_options.window.size_save || App.window.fullscreen != m_options.window.fullscreen) - window_pos_cond = ImGuiCond_Always; - - App.window.fullscreen = m_options.window.fullscreen; - App.window.size = m_options.window.size_save; - App.window.size_save = m_options.window.size_save; - App.window.centered = m_options.window.centered; - App.window.position = m_options.window.position; - App.window.auto_minimize = m_options.window.auto_minimize; - App.window.dark_mode = m_options.window.dark_mode; - App.vsync = m_options.vsync; - App.foreground_fps = m_options.foreground_fps; - App.background_fps = m_options.background_fps; - - saveBool("Screen", "fullscreen", App.window.fullscreen); - saveInt("Screen", "window_width", App.window.size.x); - saveInt("Screen", "window_height", App.window.size.y); - saveBool("Screen", "centered_window", App.window.centered); - saveInt("Screen", "window_posx", App.window.position.x); - saveInt("Screen", "window_posy", App.window.position.y); - - saveBool("Screen", "auto_minimize", App.window.auto_minimize); - saveBool("Screen", "dark_mode", App.window.dark_mode); - saveBool("Screen", "vsync", App.vsync); - - saveBool("Screen", "foreground_fps", App.foreground_fps.active); - saveInt("Screen", "foreground_fps_value", App.foreground_fps.range.value); - saveBool("Screen", "background_fps", App.background_fps.active); - saveInt("Screen", "background_fps_value", App.background_fps.range.value); - - m_changed = true; - } + if (App.window.size != m_options.window.size_save || App.window.fullscreen != m_options.window.fullscreen) + window_pos_cond = ImGuiCond_Always; + + App.window.fullscreen = m_options.window.fullscreen; + App.window.size = m_options.window.size_save; + App.window.size_save = m_options.window.size_save; + App.window.centered = m_options.window.centered; + App.window.position = m_options.window.position; + App.cursor.unlock = m_options.unlock_cursor; + App.window.auto_minimize = m_options.window.auto_minimize; + App.window.dark_mode = m_options.window.dark_mode; + App.vsync = m_options.vsync; + App.foreground_fps = m_options.foreground_fps; + App.background_fps = m_options.background_fps; + + saveBool("Screen", "fullscreen", App.window.fullscreen); + saveInt("Screen", "window_width", App.window.size.x); + saveInt("Screen", "window_height", App.window.size.y); + saveBool("Screen", "centered_window", App.window.centered); + saveInt("Screen", "window_posx", App.window.position.x); + saveInt("Screen", "window_posy", App.window.position.y); + + saveBool("Screen", "unlock_cursor", App.cursor.unlock); + saveBool("Screen", "auto_minimize", App.window.auto_minimize); + saveBool("Screen", "dark_mode", App.window.dark_mode); + saveBool("Screen", "vsync", App.vsync); + + saveBool("Screen", "foreground_fps", App.foreground_fps.active); + saveInt("Screen", "foreground_fps_value", App.foreground_fps.range.value); + saveBool("Screen", "background_fps", App.background_fps.active); + saveInt("Screen", "background_fps_value", App.background_fps.range.value); + + m_options.pos_changed = false; + m_changed = true; + } + ImGui::EndDisabled(); tabEnd(); } if (tabBegin("Graphics", 1, &active_tab)) { + drawCombo_m("Upscale Shader Preset", App.shader.presets, "", true, 17, shader_preset); + ImGui::SameLine(0.0f, 4.0f); + ImGui::BeginDisabled(App.shader.selected == App.shader.presets.selected); + if (drawButton("Apply", { 100.0f, 0.0f })) + App.shader.selected = App.shader.presets.selected; + ImGui::EndDisabled(); + drawDescription("RetroArch's slang shader preset files (.slangp).", m_colors[Color::Gray]); childBegin("##w3", true); - drawCombo_m("Upscale Shader", App.shader, "Libretro upscale shaders.", "", 17, shader) - saveInt("Graphic", "shader", App.shader.selected); drawSeparator(); drawCheckbox_m("Luma Sharpen", App.sharpen.active, "", sharpen) saveBool("Graphic", "sharpen", App.sharpen.active); @@ -276,11 +307,16 @@ void Menu::draw() drawDescription("Radius of the sampling pattern.", m_colors[Color::Gray], 12); ImGui::EndDisabled(); drawSeparator(); - drawCheckbox_m("FXAA", App.fxaa, "Fast approximate anti-aliasing.", fxaa) - saveBool("Graphic", "fxaa", App.fxaa); + drawCheckbox_m("FXAA", App.fxaa.active, "Fast approximate anti-aliasing.", fxaa) + saveBool("Graphic", "fxaa", App.fxaa.active); + ImGui::BeginDisabled(!App.fxaa.active); + drawCombo_m("", App.fxaa.presets, "FXAA quality presets.", false, 17, fxaa_preset) + saveInt("Graphic", "fxaa_preset", App.fxaa.presets.selected); + ImGui::EndDisabled(); childSeparator("##w4"); + drawSeparator(); ImGui::BeginDisabled(!ISGLIDE3X()); - drawCombo_m("Color Grading", App.lut, "Lookup table (LUT).", "", 17, lut) + drawCombo_m("Color Grading", App.lut, "Lookup table (LUT).", false, 17, lut) saveInt("Graphic", "lut", App.lut.selected); drawSeparator(); drawCheckbox_m("Bloom Effect", App.bloom.active, "", bloom) @@ -297,10 +333,16 @@ void Menu::draw() drawSeparator(); drawLabel("Stretched Viewport", m_colors[Color::Orange]); drawCheckbox_m("Horizontal", App.viewport.stretched.x, "", stretched_horizontal) + { + App.context->getCommandBuffer()->resize(); saveBool("Graphic", "stretched_horizontal", App.viewport.stretched.x); + } ImGui::SameLine(150.0f); drawCheckbox_m("Vertical", App.viewport.stretched.y, "", stretched_vertical) + { + App.context->getCommandBuffer()->resize(); saveBool("Graphic", "stretched_vertical", App.viewport.stretched.y); + } drawDescription("Stretch viewport to window size.", m_colors[Color::Gray], 14); childEnd(); tabEnd(); @@ -315,15 +357,12 @@ void Menu::draw() d2::patch_hd_text->toggle(App.hd_text.active); saveBool("Feature", "hd_text", App.hd_text.active); } - drawSlider_m(float, "", App.hd_text.scale, "%.2f", "", hd_text_scale) - { - for (int i = 0; i < 23; i++) { - const auto font = modules::HDText::Instance().getFont((uint32_t)i); - font->setSize(font->getFontSize() * App.hd_text.scale.value); - } - saveFloat("Feature", "hd_text_scale", App.hd_text.scale.value); - } - drawDescription("Scale for HD text size", m_colors[Color::Gray], 12); + ImGui::BeginDisabled(!App.hd_text.active || ISHDTEXT()); + drawSlider_m(float, "", App.hd_text.scale, "%.3f", "Global scale for HD text.", hd_text_scale) + saveFloat("Feature", "hd_text_scale", App.hd_text.scale.value); + if (App.hd_text.active) + modules::HDText::Instance().updateFontSize(); + ImGui::EndDisabled(); drawSeparator(); ImGui::BeginDisabled(!ISGLIDE3X() || !App.mini_map.available); drawCheckbox_m("Mini Map", App.mini_map.active, "Always on minimap widget.", mini_map) @@ -339,15 +378,11 @@ void Menu::draw() saveBool("Feature", "mini_map_text_over", App.mini_map.text_over); ImGui::Dummy({ 0.0f, 2.0f }); drawSlider_m(int, "", App.mini_map.width, "%d", "Minimap width.", mini_map_width_val) - { - modules::MiniMap::Instance().resize(); saveInt("Feature", "mini_map_width", App.mini_map.width.value); - } drawSlider_m(int, "", App.mini_map.height, "%d", "Minimap height.", mini_map_height_val) - { - modules::MiniMap::Instance().resize(); saveInt("Feature", "mini_map_height", App.mini_map.height.value); - } + if (App.mini_map.active) + modules::MiniMap::Instance().resize(); ImGui::EndDisabled(); ImGui::EndDisabled(); /*drawSeparator(); @@ -375,14 +410,14 @@ void Menu::draw() drawCheckbox_m("No Pickup", App.no_pickup, "Auto /nopickup option on launch (exclude 1.09d).", no_pickup) saveBool("Feature", "no_pickup", App.no_pickup); drawSeparator(); - drawCheckbox_m("Show FPS", App.show_fps, "FPS Counter on bottom center.", show_fps) - saveBool("Feature", "show_fps", App.show_fps); - drawSeparator(); - drawCheckbox_m("Unlock Cursor", App.cursor.unlock, "Cursor will not locked within window.", unlock_cursor) - saveBool("Feature", "unlock_cursor", App.cursor.unlock); + drawCheckbox_m("Show Monster Resistances", App.show_monster_res, "Show monster resistances on hp bar.", show_monster_res) + saveBool("Feature", "show_monster_res", App.show_monster_res); drawSeparator(); drawCheckbox_m("Show Item Quantity", App.show_item_quantity, "Show item quantity on bottom left corner of icon.", show_item_quantity) saveBool("Feature", "show_item_quantity", App.show_item_quantity); + drawSeparator(); + drawCheckbox_m("Show FPS", App.show_fps, "FPS Counter on bottom center.", show_fps) + saveBool("Feature", "show_fps", App.show_fps); childEnd(); tabEnd(); } @@ -541,17 +576,16 @@ bool Menu::drawCheckbox(const char* title, bool* option, const char* desc, bool* } template -bool Menu::drawCombo(const char* title, Select* select, const char* desc, const char* btn_label, int* opt, int size) +bool Menu::drawCombo(const char* title, Select* select, const char* desc, bool have_btn, int* opt, int size) { bool ret = false; - bool have_btn = (btn_label && btn_label[0]); drawLabel(title, m_colors[Color::Orange], 17); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 8.0f, 5.0f }); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0.0f, 8.0f }); if (!m_ignore_font) ImGui::PushFont(m_fonts[size]); - ImGui::SetNextItemWidth(ImGui::GetWindowContentRegionWidth() - (have_btn ? 84.0f : 0.0f)); + ImGui::SetNextItemWidth(ImGui::GetWindowContentRegionWidth() - (have_btn ? 104.0f : 0.0f)); auto& selected = select->items[select->selected]; if (ImGui::BeginCombo(("##" + std::string(title)).c_str(), selected.name.c_str(), ImGuiComboFlags_PopupAlignLeft | ImGuiComboFlags_HeightLargest)) { ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 8.0f, 8.0f }); @@ -563,8 +597,7 @@ bool Menu::drawCombo(const char* title, Select* select, const char* desc, con select->selected = i; if (select->selected != *opt) { *opt = select->selected; - if (!have_btn) - ret = true; + ret = true; } } if (is_selected) { @@ -575,12 +608,6 @@ bool Menu::drawCombo(const char* title, Select* select, const char* desc, con ImGui::PopStyleVar(); ImGui::EndCombo(); } - if (have_btn) { - ImGui::SameLine(0.0f, 4.0f); - ImGui::PushStyleColor(ImGuiCol_Text, m_colors[Color::Orange]); - ret = ImGui::Button(btn_label, { 80.0f, 0.0f }); - ImGui::PopStyleColor(); - } if (!m_ignore_font) ImGui::PopFont(); ImGui::PopStyleVar(2); @@ -643,6 +670,24 @@ bool Menu::drawSlider(const std::string& id, const char* title, Range* range, return false; } +bool Menu::drawButton(const char* label, const ImVec2& btn_size, int size) +{ + bool ret = false; + + ImGui::PushStyleColor(ImGuiCol_Text, m_colors[Color::Orange]); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 8.0f, 5.0f }); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0.0f, 8.0f }); + if (!m_ignore_font) + ImGui::PushFont(m_fonts[size]); + if (ImGui::Button(label, btn_size)) + ret = true; + if (!m_ignore_font) + ImGui::PopFont(); + ImGui::PopStyleVar(2); + ImGui::PopStyleColor(); + return ret; +} + void Menu::drawSeparator(float y_padd, float alpha) { ImGui::Dummy({ 0.0f, y_padd - 1.0f }); diff --git a/d2gl/src/option/menu.h b/d2gl/src/option/menu.h index 45021a1..5512b34 100644 --- a/d2gl/src/option/menu.h +++ b/d2gl/src/option/menu.h @@ -31,15 +31,18 @@ enum class Color { struct Options { bool vsync = false; + bool unlock_cursor = false; D2GLApp::Window window; D2GLApp::ForegroundFPS foreground_fps; D2GLApp::BackgroundFPS background_fps; + bool pos_changed = false; }; class Menu { bool m_visible = false; bool m_closing = false; bool m_changed = false; + bool m_opt_changed = false; std::unordered_map m_fonts; std::unordered_map m_colors; Options m_options; @@ -57,12 +60,13 @@ class Menu { bool drawNav(const char* btn_label); template - bool drawCombo(const char* title, Select* select, const char* desc, const char* btn_label, int* opt, int size = 17); + bool drawCombo(const char* title, Select* select, const char* desc, bool have_btn, int* opt, int size = 17); bool drawCheckbox(const char* title, bool* option, const char* desc, bool* opt); template bool drawSlider(const std::string& id, const char* title, Range* range, const char* format, const char* desc, T* opt); void drawInput2(const std::string& id, const char* desc, glm::ivec2* input, glm::ivec2 min = { 0, 0 }, glm::ivec2 max = { 10000, 10000 }); + bool drawButton(const char* label, const ImVec2& btn_size = { 0.0f, 0.0f }, int size = 17); void drawSeparator(float y_padd = 5.0f, float alpha = 1.0f); void drawLabel(const char* title, const ImVec4& color, int size = 17); void drawDescription(const char* desc, const ImVec4& color, int size = 14); diff --git a/d2gl/src/win32.cpp b/d2gl/src/win32.cpp index a741744..61ee5ea 100644 --- a/d2gl/src/win32.cpp +++ b/d2gl/src/win32.cpp @@ -142,6 +142,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) option->window.position.x = rect->left; option->window.position.y = rect->top; option->window.centered = false; + option->pos_changed = true; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } diff --git a/d2gl/vendor/include/glslang/glslang.h b/d2gl/vendor/include/glslang/glslang.h index 3793b29..ec37014 100644 --- a/d2gl/vendor/include/glslang/glslang.h +++ b/d2gl/vendor/include/glslang/glslang.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include namespace glslang { @@ -15,9 +17,11 @@ struct GLVersion { }; struct Result { - bool result; - std::string msg; - std::string str; + bool result = false; + std::string source; + std::string err_msg; + std::vector samplers; + std::unordered_map uniforms; }; Result getGLSLCode( diff --git a/d2gl/vendor/lib/Debug/glslang.lib b/d2gl/vendor/lib/Debug/glslang.lib index 5295607..62bece0 100644 Binary files a/d2gl/vendor/lib/Debug/glslang.lib and b/d2gl/vendor/lib/Debug/glslang.lib differ diff --git a/d2gl/vendor/lib/Release/glslang.lib b/d2gl/vendor/lib/Release/glslang.lib index 1f5680c..7c36a48 100644 Binary files a/d2gl/vendor/lib/Release/glslang.lib and b/d2gl/vendor/lib/Release/glslang.lib differ diff --git a/ddraw/ddraw.rc b/ddraw/ddraw.rc index 44c7af9..23fdd9d 100644 Binary files a/ddraw/ddraw.rc and b/ddraw/ddraw.rc differ diff --git a/glide3x/glide3x.rc b/glide3x/glide3x.rc index 4b7fa49..60ce047 100644 Binary files a/glide3x/glide3x.rc and b/glide3x/glide3x.rc differ diff --git a/glide3x/src/glide/glide3x.cpp b/glide3x/src/glide/glide3x.cpp index ddbe55c..befab0a 100644 --- a/glide3x/src/glide/glide3x.cpp +++ b/glide3x/src/glide/glide3x.cpp @@ -225,9 +225,6 @@ FX_ENTRY void FX_CALL grGlideShutdown(void) } // Unused functions -// These functions seems doesn't called at all in any version -// No assetion fail reports -/* FX_ENTRY FxI32 FX_CALL grQueryResolutions(const GrResolution* resTemplate, GrResolution* output) { assert(false); @@ -494,7 +491,7 @@ FX_ENTRY void FX_CALL grDisableAllEffects(void) { assert(false); } -*/ + #ifdef __cplusplus } #endif \ No newline at end of file