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