mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-19 11:23:42 +00:00
Graphics Preferences: Anti-aliasing + FPS (#13538)
* Expose Antialiasing velues Expose Antialiasing multipliers. Default to 4 as current implementation but enables the user to disable it to improve performante or increase sampling to improve quality. * FXAA * Improve descriptions * Require restart when MSAA setting changes Detect changes to the OpenGL MSAA (multisample anti-aliasing) preference when opening Preferences and prompt the user to restart the application to apply the change. Adds a constant key for the MSAA setting, stores the previous value, checks for changes (similar to the existing FXAA handling), and shows a warning dialog explaining the restart will close the current project without saving. If the user accepts, recreate_GUI is invoked to apply the MSAA change immediately. * Revert "Require restart when MSAA setting changes" This reverts commit dde134d346c3849598c91d025d2faed1b51c8a22. * Menu and FPS options * Fix FPS limiter and remove VSYNC * Grouped FPS settings and mode up rigth fps counter --------- Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
This commit is contained in:
50
resources/shaders/110/fxaa.fs
Normal file
50
resources/shaders/110/fxaa.fs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#version 110
|
||||||
|
|
||||||
|
uniform sampler2D uniform_texture;
|
||||||
|
uniform vec2 inv_tex_size;
|
||||||
|
|
||||||
|
varying vec2 tex_coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 rgbNW = texture2D(uniform_texture, tex_coord + vec2(-1.0, -1.0) * inv_tex_size).rgb;
|
||||||
|
vec3 rgbNE = texture2D(uniform_texture, tex_coord + vec2(1.0, -1.0) * inv_tex_size).rgb;
|
||||||
|
vec3 rgbSW = texture2D(uniform_texture, tex_coord + vec2(-1.0, 1.0) * inv_tex_size).rgb;
|
||||||
|
vec3 rgbSE = texture2D(uniform_texture, tex_coord + vec2(1.0, 1.0) * inv_tex_size).rgb;
|
||||||
|
vec3 rgbM = texture2D(uniform_texture, tex_coord).rgb;
|
||||||
|
|
||||||
|
vec3 luma_coeff = vec3(0.299, 0.587, 0.114);
|
||||||
|
float lumaNW = dot(rgbNW, luma_coeff);
|
||||||
|
float lumaNE = dot(rgbNE, luma_coeff);
|
||||||
|
float lumaSW = dot(rgbSW, luma_coeff);
|
||||||
|
float lumaSE = dot(rgbSE, luma_coeff);
|
||||||
|
float lumaM = dot(rgbM, luma_coeff);
|
||||||
|
|
||||||
|
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
||||||
|
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
||||||
|
|
||||||
|
vec2 dir;
|
||||||
|
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||||
|
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||||
|
|
||||||
|
const float FXAA_REDUCE_MIN = 1.0 / 128.0;
|
||||||
|
const float FXAA_REDUCE_MUL = 1.0 / 8.0;
|
||||||
|
const float FXAA_SPAN_MAX = 8.0;
|
||||||
|
|
||||||
|
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
|
||||||
|
float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
|
||||||
|
dir = min(vec2(FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX), dir * rcpDirMin)) * inv_tex_size;
|
||||||
|
|
||||||
|
vec3 rgbA = 0.5 * (
|
||||||
|
texture2D(uniform_texture, tex_coord + dir * (1.0 / 3.0 - 0.5)).rgb +
|
||||||
|
texture2D(uniform_texture, tex_coord + dir * (2.0 / 3.0 - 0.5)).rgb
|
||||||
|
);
|
||||||
|
|
||||||
|
vec3 rgbB = rgbA * 0.5 + 0.25 * (
|
||||||
|
texture2D(uniform_texture, tex_coord + dir * -0.5).rgb +
|
||||||
|
texture2D(uniform_texture, tex_coord + dir * 0.5).rgb
|
||||||
|
);
|
||||||
|
|
||||||
|
float lumaB = dot(rgbB, luma_coeff);
|
||||||
|
gl_FragColor = (lumaB < lumaMin || lumaB > lumaMax) ? vec4(rgbA, 1.0) : vec4(rgbB, 1.0);
|
||||||
|
}
|
||||||
15
resources/shaders/110/fxaa.vs
Normal file
15
resources/shaders/110/fxaa.vs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#version 110
|
||||||
|
|
||||||
|
uniform mat4 view_model_matrix;
|
||||||
|
uniform mat4 projection_matrix;
|
||||||
|
|
||||||
|
attribute vec3 v_position;
|
||||||
|
attribute vec2 v_tex_coord;
|
||||||
|
|
||||||
|
varying vec2 tex_coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
tex_coord = v_tex_coord;
|
||||||
|
gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
|
||||||
|
}
|
||||||
52
resources/shaders/140/fxaa.fs
Normal file
52
resources/shaders/140/fxaa.fs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#version 140
|
||||||
|
|
||||||
|
uniform sampler2D uniform_texture;
|
||||||
|
uniform vec2 inv_tex_size;
|
||||||
|
|
||||||
|
in vec2 tex_coord;
|
||||||
|
|
||||||
|
out vec4 out_color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 rgbNW = texture(uniform_texture, tex_coord + vec2(-1.0, -1.0) * inv_tex_size).rgb;
|
||||||
|
vec3 rgbNE = texture(uniform_texture, tex_coord + vec2(1.0, -1.0) * inv_tex_size).rgb;
|
||||||
|
vec3 rgbSW = texture(uniform_texture, tex_coord + vec2(-1.0, 1.0) * inv_tex_size).rgb;
|
||||||
|
vec3 rgbSE = texture(uniform_texture, tex_coord + vec2(1.0, 1.0) * inv_tex_size).rgb;
|
||||||
|
vec3 rgbM = texture(uniform_texture, tex_coord).rgb;
|
||||||
|
|
||||||
|
vec3 luma_coeff = vec3(0.299, 0.587, 0.114);
|
||||||
|
float lumaNW = dot(rgbNW, luma_coeff);
|
||||||
|
float lumaNE = dot(rgbNE, luma_coeff);
|
||||||
|
float lumaSW = dot(rgbSW, luma_coeff);
|
||||||
|
float lumaSE = dot(rgbSE, luma_coeff);
|
||||||
|
float lumaM = dot(rgbM, luma_coeff);
|
||||||
|
|
||||||
|
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
||||||
|
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
||||||
|
|
||||||
|
vec2 dir;
|
||||||
|
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||||
|
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||||
|
|
||||||
|
const float FXAA_REDUCE_MIN = 1.0 / 128.0;
|
||||||
|
const float FXAA_REDUCE_MUL = 1.0 / 8.0;
|
||||||
|
const float FXAA_SPAN_MAX = 8.0;
|
||||||
|
|
||||||
|
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
|
||||||
|
float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
|
||||||
|
dir = min(vec2(FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX), dir * rcpDirMin)) * inv_tex_size;
|
||||||
|
|
||||||
|
vec3 rgbA = 0.5 * (
|
||||||
|
texture(uniform_texture, tex_coord + dir * (1.0 / 3.0 - 0.5)).rgb +
|
||||||
|
texture(uniform_texture, tex_coord + dir * (2.0 / 3.0 - 0.5)).rgb
|
||||||
|
);
|
||||||
|
|
||||||
|
vec3 rgbB = rgbA * 0.5 + 0.25 * (
|
||||||
|
texture(uniform_texture, tex_coord + dir * -0.5).rgb +
|
||||||
|
texture(uniform_texture, tex_coord + dir * 0.5).rgb
|
||||||
|
);
|
||||||
|
|
||||||
|
float lumaB = dot(rgbB, luma_coeff);
|
||||||
|
out_color = (lumaB < lumaMin || lumaB > lumaMax) ? vec4(rgbA, 1.0) : vec4(rgbB, 1.0);
|
||||||
|
}
|
||||||
15
resources/shaders/140/fxaa.vs
Normal file
15
resources/shaders/140/fxaa.vs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#version 140
|
||||||
|
|
||||||
|
uniform mat4 view_model_matrix;
|
||||||
|
uniform mat4 projection_matrix;
|
||||||
|
|
||||||
|
in vec3 v_position;
|
||||||
|
in vec2 v_tex_coord;
|
||||||
|
|
||||||
|
out vec2 tex_coord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
tex_coord = v_tex_coord;
|
||||||
|
gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
|
||||||
|
}
|
||||||
@@ -230,6 +230,29 @@ void AppConfig::set_defaults()
|
|||||||
if (get("camera_orbit_mult").empty())
|
if (get("camera_orbit_mult").empty())
|
||||||
set("camera_orbit_mult", "1.0");
|
set("camera_orbit_mult", "1.0");
|
||||||
|
|
||||||
|
if (get(SETTING_OPENGL_AA_SAMPLES).empty())
|
||||||
|
set(SETTING_OPENGL_AA_SAMPLES, "4");
|
||||||
|
|
||||||
|
if (get(SETTING_OPENGL_FXAA_ENABLED).empty())
|
||||||
|
set_bool(SETTING_OPENGL_FXAA_ENABLED, false);
|
||||||
|
|
||||||
|
if (get(SETTING_OPENGL_FPS_CAP).empty())
|
||||||
|
set(SETTING_OPENGL_FPS_CAP, "0");
|
||||||
|
else {
|
||||||
|
int fps_cap = 0;
|
||||||
|
try {
|
||||||
|
fps_cap = std::stoi(get(SETTING_OPENGL_FPS_CAP));
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
fps_cap = 0;
|
||||||
|
}
|
||||||
|
fps_cap = std::max(0, std::min(fps_cap, 240));
|
||||||
|
set(SETTING_OPENGL_FPS_CAP, std::to_string(fps_cap));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get(SETTING_OPENGL_SHOW_FPS_OVERLAY).empty())
|
||||||
|
set_bool(SETTING_OPENGL_SHOW_FPS_OVERLAY, false);
|
||||||
|
|
||||||
if (get("export_sources_full_pathnames").empty())
|
if (get("export_sources_full_pathnames").empty())
|
||||||
set_bool("export_sources_full_pathnames", false);
|
set_bool("export_sources_full_pathnames", false);
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ using namespace nlohmann;
|
|||||||
#define SETTING_NETWORK_PLUGIN_REMIND_LATER "network_plugin_remind_later"
|
#define SETTING_NETWORK_PLUGIN_REMIND_LATER "network_plugin_remind_later"
|
||||||
#define SETTING_USE_ENCRYPTED_TOKEN_FILE "use_encrypted_token_file"
|
#define SETTING_USE_ENCRYPTED_TOKEN_FILE "use_encrypted_token_file"
|
||||||
#define SETTING_CLOUD_PROVIDERS "cloud_providers"
|
#define SETTING_CLOUD_PROVIDERS "cloud_providers"
|
||||||
|
#define SETTING_OPENGL_AA_SAMPLES "opengl_antialiasing_samples"
|
||||||
|
#define SETTING_OPENGL_FXAA_ENABLED "opengl_fxaa_enabled"
|
||||||
|
#define SETTING_OPENGL_FPS_CAP "opengl_fps_cap"
|
||||||
|
#define SETTING_OPENGL_SHOW_FPS_OVERLAY "opengl_show_fps_overlay"
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
#define BAMBU_NETWORK_AGENT_VERSION_LEGACY "01.10.01.09"
|
#define BAMBU_NETWORK_AGENT_VERSION_LEGACY "01.10.01.09"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "libslic3r/Technologies.hpp"
|
#include "libslic3r/Technologies.hpp"
|
||||||
#include "libslic3r/Tesselate.hpp"
|
#include "libslic3r/Tesselate.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
|
#include "libslic3r/AppConfig.hpp"
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
#include "BackgroundSlicingProcess.hpp"
|
#include "BackgroundSlicingProcess.hpp"
|
||||||
#include "GLShader.hpp"
|
#include "GLShader.hpp"
|
||||||
@@ -1202,6 +1203,11 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
|||||||
|
|
||||||
GLCanvas3D::~GLCanvas3D()
|
GLCanvas3D::~GLCanvas3D()
|
||||||
{
|
{
|
||||||
|
if (m_fxaa_texture_id != 0 && _set_current()) {
|
||||||
|
glsafe(::glDeleteTextures(1, &m_fxaa_texture_id));
|
||||||
|
m_fxaa_texture_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
reset_volumes();
|
reset_volumes();
|
||||||
|
|
||||||
m_sel_plate_toolbar.del_all_item();
|
m_sel_plate_toolbar.del_all_item();
|
||||||
@@ -2082,9 +2088,16 @@ void GLCanvas3D::render(bool only_init)
|
|||||||
if (m_picking_enabled && m_rectangle_selection.is_dragging())
|
if (m_picking_enabled && m_rectangle_selection.is_dragging())
|
||||||
m_rectangle_selection.render(*this);
|
m_rectangle_selection.render(*this);
|
||||||
|
|
||||||
|
if (_is_fxaa_enabled())
|
||||||
|
_render_fxaa_pass(static_cast<unsigned int>(cnv_size.get_width()), static_cast<unsigned int>(cnv_size.get_height()));
|
||||||
|
|
||||||
// draw overlays
|
// draw overlays
|
||||||
_render_overlays();
|
_render_overlays();
|
||||||
|
|
||||||
|
const int current_fps = m_render_stats.get_fps_and_reset_if_needed();
|
||||||
|
if (_is_fps_overlay_enabled())
|
||||||
|
_render_fps_overlay(current_fps);
|
||||||
|
|
||||||
if (wxGetApp().plater()->is_render_statistic_dialog_visible()) {
|
if (wxGetApp().plater()->is_render_statistic_dialog_visible()) {
|
||||||
ImGui::ShowMetricsWindow();
|
ImGui::ShowMetricsWindow();
|
||||||
|
|
||||||
@@ -2092,7 +2105,7 @@ void GLCanvas3D::render(bool only_init)
|
|||||||
imgui.begin(std::string("Render statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
imgui.begin(std::string("Render statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||||
imgui.text("FPS (SwapBuffers() calls per second):");
|
imgui.text("FPS (SwapBuffers() calls per second):");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
imgui.text(std::to_string(m_render_stats.get_fps_and_reset_if_needed()));
|
imgui.text(std::to_string(current_fps));
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
imgui.text("Compressed textures:");
|
imgui.text("Compressed textures:");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -3194,6 +3207,22 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
|||||||
wxGetApp().imgui()->reset_requires_extra_frame();
|
wxGetApp().imgui()->reset_requires_extra_frame();
|
||||||
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
|
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
|
||||||
|
|
||||||
|
const int fps_cap = _get_effective_fps_cap();
|
||||||
|
if (fps_cap > 0) {
|
||||||
|
const auto now = std::chrono::steady_clock::now();
|
||||||
|
const auto min_frame_time = std::chrono::duration<double>(1.0 / static_cast<double>(fps_cap));
|
||||||
|
const auto elapsed = now - m_last_frame_start_time;
|
||||||
|
if (elapsed < min_frame_time) {
|
||||||
|
const int wait_ms = std::max(1, static_cast<int>(std::ceil(std::chrono::duration<double, std::milli>(min_frame_time - elapsed).count())));
|
||||||
|
schedule_extra_frame(wait_ms);
|
||||||
|
evt.RequestMore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pace by frame-start interval so rendering time is part of the target budget.
|
||||||
|
m_last_frame_start_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
_refresh_if_shown_on_screen();
|
_refresh_if_shown_on_screen();
|
||||||
|
|
||||||
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
|
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
|
||||||
@@ -7422,6 +7451,105 @@ void GLCanvas3D::_rectangular_selection_picking_pass()
|
|||||||
_update_volumes_hover_state();
|
_update_volumes_hover_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLCanvas3D::_is_fxaa_enabled() const
|
||||||
|
{
|
||||||
|
return wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_FXAA_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GLCanvas3D::_get_effective_fps_cap() const
|
||||||
|
{
|
||||||
|
if (wxGetApp().app_config == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int fps_cap = 0;
|
||||||
|
try {
|
||||||
|
fps_cap = std::stoi(wxGetApp().app_config->get(SETTING_OPENGL_FPS_CAP));
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
fps_cap = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fps_cap = std::max(0, std::min(fps_cap, 240));
|
||||||
|
|
||||||
|
return fps_cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLCanvas3D::_is_fps_overlay_enabled() const
|
||||||
|
{
|
||||||
|
return wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_SHOW_FPS_OVERLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_render_fps_overlay(int fps) const
|
||||||
|
{
|
||||||
|
if (fps < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
|
const float margin = 10.0f * get_scale();
|
||||||
|
const ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(display_size.x - margin, margin), ImGuiCond_Always, ImVec2(1.0f, 0.0f));
|
||||||
|
ImGui::SetNextWindowBgAlpha(0.35f);
|
||||||
|
imgui.begin(
|
||||||
|
std::string("###fps_overlay"),
|
||||||
|
ImGuiWindowFlags_AlwaysAutoResize |
|
||||||
|
ImGuiWindowFlags_NoResize |
|
||||||
|
ImGuiWindowFlags_NoCollapse |
|
||||||
|
ImGuiWindowFlags_NoTitleBar |
|
||||||
|
ImGuiWindowFlags_NoMove |
|
||||||
|
ImGuiWindowFlags_NoSavedSettings |
|
||||||
|
ImGuiWindowFlags_NoInputs);
|
||||||
|
imgui.text(std::string("FPS: ") + std::to_string(fps));
|
||||||
|
imgui.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_render_fxaa_pass(unsigned int width, unsigned int height)
|
||||||
|
{
|
||||||
|
if (width == 0 || height == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GLShaderProgram* shader = wxGetApp().get_shader("fxaa");
|
||||||
|
if (shader == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_fxaa_texture_id == 0) {
|
||||||
|
glsafe(::glGenTextures(1, &m_fxaa_texture_id));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, m_fxaa_texture_id));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, m_fxaa_texture_id));
|
||||||
|
if (m_fxaa_texture_size[0] != width || m_fxaa_texture_size[1] != height) {
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
m_fxaa_texture_size = { width, height };
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height));
|
||||||
|
|
||||||
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
|
glsafe(::glDisable(GL_BLEND));
|
||||||
|
glsafe(::glClear(GL_COLOR_BUFFER_BIT));
|
||||||
|
|
||||||
|
shader->start_using();
|
||||||
|
shader->set_uniform("view_model_matrix", Transform3d::Identity());
|
||||||
|
shader->set_uniform("projection_matrix", Transform3d::Identity());
|
||||||
|
shader->set_uniform("uniform_texture", 0);
|
||||||
|
shader->set_uniform("inv_tex_size", Vec2f(1.0f / static_cast<float>(width), 1.0f / static_cast<float>(height)));
|
||||||
|
|
||||||
|
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, m_fxaa_texture_id));
|
||||||
|
m_background.render();
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
shader->stop_using();
|
||||||
|
|
||||||
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
glsafe(::glEnable(GL_BLEND));
|
||||||
|
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_render_background()
|
void GLCanvas3D::_render_background()
|
||||||
{
|
{
|
||||||
bool use_error_color = false;
|
bool use_error_color = false;
|
||||||
|
|||||||
@@ -607,6 +607,7 @@ private:
|
|||||||
bool m_reload_delayed;
|
bool m_reload_delayed;
|
||||||
|
|
||||||
RenderStats m_render_stats;
|
RenderStats m_render_stats;
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> m_last_frame_start_time{ std::chrono::steady_clock::now() };
|
||||||
|
|
||||||
int m_imgui_undo_redo_hovered_pos{ -1 };
|
int m_imgui_undo_redo_hovered_pos{ -1 };
|
||||||
int m_mouse_wheel{ 0 };
|
int m_mouse_wheel{ 0 };
|
||||||
@@ -724,6 +725,8 @@ public:
|
|||||||
CameraTarget m_camera_target;
|
CameraTarget m_camera_target;
|
||||||
#endif // ENABLE_SHOW_CAMERA_TARGET
|
#endif // ENABLE_SHOW_CAMERA_TARGET
|
||||||
GLModel m_background;
|
GLModel m_background;
|
||||||
|
unsigned int m_fxaa_texture_id{ 0 };
|
||||||
|
std::array<unsigned int, 2> m_fxaa_texture_size{ 0, 0 };
|
||||||
public:
|
public:
|
||||||
explicit GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed);
|
explicit GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed);
|
||||||
~GLCanvas3D();
|
~GLCanvas3D();
|
||||||
@@ -1231,6 +1234,11 @@ private:
|
|||||||
|
|
||||||
void _picking_pass();
|
void _picking_pass();
|
||||||
void _rectangular_selection_picking_pass();
|
void _rectangular_selection_picking_pass();
|
||||||
|
bool _is_fxaa_enabled() const;
|
||||||
|
int _get_effective_fps_cap() const;
|
||||||
|
bool _is_fps_overlay_enabled() const;
|
||||||
|
void _render_fps_overlay(int fps) const;
|
||||||
|
void _render_fxaa_pass(unsigned int width, unsigned int height);
|
||||||
void _render_background();
|
void _render_background();
|
||||||
void _render_bed(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_axes);
|
void _render_bed(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_axes);
|
||||||
//BBS: add part plate related logic
|
//BBS: add part plate related logic
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ std::pair<bool, std::string> GLShadersManager::init()
|
|||||||
valid &= append_shader("flat_clip", { prefix + "flat_clip.vs", prefix + "flat_clip.fs" });
|
valid &= append_shader("flat_clip", { prefix + "flat_clip.vs", prefix + "flat_clip.fs" });
|
||||||
// basic shader for textures, used to render textures
|
// basic shader for textures, used to render textures
|
||||||
valid &= append_shader("flat_texture", { prefix + "flat_texture.vs", prefix + "flat_texture.fs" });
|
valid &= append_shader("flat_texture", { prefix + "flat_texture.vs", prefix + "flat_texture.fs" });
|
||||||
|
// used to apply post-processing antialiasing in screen space
|
||||||
|
valid &= append_shader("fxaa", { prefix + "fxaa.vs", prefix + "fxaa.fs" });
|
||||||
// used to render 3D scene background
|
// used to render 3D scene background
|
||||||
valid &= append_shader("background", { prefix + "background.vs", prefix + "background.fs" });
|
valid &= append_shader("background", { prefix + "background.vs", prefix + "background.fs" });
|
||||||
#if SLIC3R_OPENGL_ES
|
#if SLIC3R_OPENGL_ES
|
||||||
|
|||||||
@@ -7553,6 +7553,13 @@ void GUI_App::open_exportpresetbundledialog(size_t open_on_tab, const std::strin
|
|||||||
|
|
||||||
void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_option)
|
void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_option)
|
||||||
{
|
{
|
||||||
|
static constexpr const char* opengl_fxaa_setting_key = "opengl_fxaa_enabled";
|
||||||
|
static constexpr const char* opengl_fps_cap_setting_key = "opengl_fps_cap";
|
||||||
|
static constexpr const char* opengl_show_fps_overlay_setting_key = "opengl_show_fps_overlay";
|
||||||
|
const std::string previous_opengl_fxaa = app_config->get(opengl_fxaa_setting_key);
|
||||||
|
const std::string previous_opengl_fps_cap = app_config->get(opengl_fps_cap_setting_key);
|
||||||
|
const std::string previous_opengl_show_fps_overlay = app_config->get(opengl_show_fps_overlay_setting_key);
|
||||||
|
|
||||||
bool need_recreate_gui = false;
|
bool need_recreate_gui = false;
|
||||||
std::string pending_language;
|
std::string pending_language;
|
||||||
{
|
{
|
||||||
@@ -7591,6 +7598,14 @@ void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool opengl_fxaa_changed = app_config->get(opengl_fxaa_setting_key) != previous_opengl_fxaa;
|
||||||
|
const bool opengl_fps_cap_changed = app_config->get(opengl_fps_cap_setting_key) != previous_opengl_fps_cap;
|
||||||
|
const bool opengl_show_fps_overlay_changed = app_config->get(opengl_show_fps_overlay_setting_key) != previous_opengl_show_fps_overlay;
|
||||||
|
if ((opengl_fxaa_changed || opengl_fps_cap_changed || opengl_show_fps_overlay_changed) && !need_recreate_gui && this->plater_ != nullptr) {
|
||||||
|
this->plater_->set_current_canvas_as_dirty();
|
||||||
|
this->plater_->get_current_canvas3D()->force_set_focus();
|
||||||
|
}
|
||||||
|
|
||||||
if (!pending_language.empty()) {
|
if (!pending_language.empty()) {
|
||||||
const std::string previous_language = app_config->get("language");
|
const std::string previous_language = app_config->get("language");
|
||||||
app_config->set("language", pending_language);
|
app_config->set("language", pending_language);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
|
|
||||||
|
#include "libslic3r/AppConfig.hpp"
|
||||||
#include "libslic3r/Platform.hpp"
|
#include "libslic3r/Platform.hpp"
|
||||||
|
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
@@ -408,6 +409,13 @@ wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas, const std::pair<i
|
|||||||
|
|
||||||
wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent)
|
wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent)
|
||||||
{
|
{
|
||||||
|
int antialiasing_samples = 4;
|
||||||
|
if (const AppConfig* app_config = get_app_config(); app_config != nullptr) {
|
||||||
|
const std::string value = app_config->get(SETTING_OPENGL_AA_SAMPLES);
|
||||||
|
if (value == "0" || value == "2" || value == "4" || value == "8" || value == "16")
|
||||||
|
antialiasing_samples = ::atoi(value.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
int attribList[] = {
|
int attribList[] = {
|
||||||
WX_GL_RGBA,
|
WX_GL_RGBA,
|
||||||
WX_GL_DOUBLEBUFFER,
|
WX_GL_DOUBLEBUFFER,
|
||||||
@@ -421,19 +429,26 @@ wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent)
|
|||||||
WX_GL_DEPTH_SIZE, 24,
|
WX_GL_DEPTH_SIZE, 24,
|
||||||
//BBS: turn on stencil buffer for outline
|
//BBS: turn on stencil buffer for outline
|
||||||
WX_GL_STENCIL_SIZE, 8,
|
WX_GL_STENCIL_SIZE, 8,
|
||||||
WX_GL_SAMPLE_BUFFERS, GL_TRUE,
|
WX_GL_SAMPLE_BUFFERS, antialiasing_samples > 0 ? GL_TRUE : GL_FALSE,
|
||||||
WX_GL_SAMPLES, 4,
|
WX_GL_SAMPLES, antialiasing_samples,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (s_multisample == EMultisampleState::Unknown) {
|
constexpr int sample_buffers_value_idx = 15;
|
||||||
|
constexpr int samples_value_idx = 17;
|
||||||
|
|
||||||
|
if (antialiasing_samples <= 0)
|
||||||
|
s_multisample = EMultisampleState::Disabled;
|
||||||
|
else if (s_multisample == EMultisampleState::Unknown) {
|
||||||
detect_multisample(attribList);
|
detect_multisample(attribList);
|
||||||
// // debug output
|
// // debug output
|
||||||
// std::cout << "Multisample " << (can_multisample() ? "enabled" : "disabled") << std::endl;
|
// std::cout << "Multisample " << (can_multisample() ? "enabled" : "disabled") << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! can_multisample())
|
if (! can_multisample()) {
|
||||||
attribList[12] = 0;
|
attribList[sample_buffers_value_idx] = GL_FALSE;
|
||||||
|
attribList[samples_value_idx] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
wxGLCanvas* canvas = new wxGLCanvas(&parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
|
wxGLCanvas* canvas = new wxGLCanvas(&parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
|
||||||
// The GL canvas paints its entire surface, so background erasing is unnecessary.
|
// The GL canvas paints its entire surface, so background erasing is unnecessary.
|
||||||
|
|||||||
@@ -114,7 +114,8 @@ wxBoxSizer *PreferencesDialog::create_item_combobox(wxString title, wxString too
|
|||||||
if (!current_setting.empty()) {
|
if (!current_setting.empty()) {
|
||||||
auto compare = [current_setting](string possible_setting) { return current_setting == possible_setting; };
|
auto compare = [current_setting](string possible_setting) { return current_setting == possible_setting; };
|
||||||
auto iterator = find_if(config_name_index.begin(), config_name_index.end(), compare);
|
auto iterator = find_if(config_name_index.begin(), config_name_index.end(), compare);
|
||||||
current_index = iterator - config_name_index.begin();
|
if (iterator != config_name_index.end())
|
||||||
|
current_index = static_cast<unsigned int>(iterator - config_name_index.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [sizer, combobox] = create_item_combobox_base(title, tooltip, param, vlist, current_index);
|
auto [sizer, combobox] = create_item_combobox_base(title, tooltip, param, vlist, current_index);
|
||||||
@@ -1526,6 +1527,64 @@ void PreferencesDialog::create_items()
|
|||||||
g_sizer->AddSpacer(FromDIP(10));
|
g_sizer->AddSpacer(FromDIP(10));
|
||||||
sizer_page->Add(g_sizer, 0, wxEXPAND);
|
sizer_page->Add(g_sizer, 0, wxEXPAND);
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
//// GRAPHICS TAB
|
||||||
|
/////////////////////////////////////
|
||||||
|
m_pref_tabs->AppendItem(_L("Graphics"));
|
||||||
|
f_sizers.push_back(new wxFlexGridSizer(1, 1, v_gap, 0));
|
||||||
|
g_sizer = f_sizers.back();
|
||||||
|
g_sizer->AddGrowableCol(0, 1);
|
||||||
|
|
||||||
|
//// GRAPHICS > Anti-aliasing
|
||||||
|
g_sizer->Add(create_item_title(_L("Anti-aliasing")), 1, wxEXPAND);
|
||||||
|
|
||||||
|
auto item_antialiasing = create_item_combobox(
|
||||||
|
_L("MSAA Multiplier"),
|
||||||
|
_L("Set the Multi-Sample Anti-Aliasing level.\n"
|
||||||
|
"Higher values result in smoother edges, but the impact on performance is exponential.\n"
|
||||||
|
"Lower values improve performance, at the cost of jagged edges.\n"
|
||||||
|
"If disabled, its recommended to enable FXAA to reduce jagged edges with minimal performance impact.\n\n"
|
||||||
|
"Requires application restart."),
|
||||||
|
SETTING_OPENGL_AA_SAMPLES,
|
||||||
|
{_L("Disabled"), "2x", "4x", "8x", "16x"},
|
||||||
|
{"0", "2", "4", "8", "16"}
|
||||||
|
);
|
||||||
|
g_sizer->Add(item_antialiasing);
|
||||||
|
|
||||||
|
auto item_fxaa = create_item_checkbox(
|
||||||
|
_L("FXAA post-processing"),
|
||||||
|
_L("Applies Fast Approximate Anti-Aliasing as a screen-space pass.\n"
|
||||||
|
"Useful for disabling or reducing the MSAA setting to improve performance.\n\n"
|
||||||
|
"Takes effect immediately."),
|
||||||
|
SETTING_OPENGL_FXAA_ENABLED
|
||||||
|
);
|
||||||
|
g_sizer->Add(item_fxaa);
|
||||||
|
|
||||||
|
//// GRAPHICS > FPS
|
||||||
|
g_sizer->Add(create_item_title(_L("FPS")), 1, wxEXPAND);
|
||||||
|
|
||||||
|
auto item_fps_cap = create_item_spinctrl(
|
||||||
|
_L("FPS cap"),
|
||||||
|
_L("(0 = unlimited)"),
|
||||||
|
_L("FPS"),
|
||||||
|
_L("Limits viewport frame rate to reduce GPU load and power usage.\n"
|
||||||
|
"Set to 0 for unlimited frame rate."),
|
||||||
|
SETTING_OPENGL_FPS_CAP,
|
||||||
|
0,
|
||||||
|
240
|
||||||
|
);
|
||||||
|
g_sizer->Add(item_fps_cap);
|
||||||
|
|
||||||
|
auto item_fps_overlay = create_item_checkbox(
|
||||||
|
_L("Show FPS overlay"),
|
||||||
|
_L("Displays current viewport FPS in the top-right corner."),
|
||||||
|
SETTING_OPENGL_SHOW_FPS_OVERLAY
|
||||||
|
);
|
||||||
|
g_sizer->Add(item_fps_overlay);
|
||||||
|
|
||||||
|
g_sizer->AddSpacer(FromDIP(10));
|
||||||
|
sizer_page->Add(g_sizer, 0, wxEXPAND);
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
//// ONLINE TAB
|
//// ONLINE TAB
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
|
|||||||
Reference in New Issue
Block a user