remove all async_start/end calls
This commit is contained in:
157
src/app.cpp
157
src/app.cpp
@@ -566,22 +566,87 @@ bool App::update_ui_observer(Node *n)
|
||||
return false;
|
||||
}
|
||||
|
||||
void App::update(float dt)
|
||||
void App::draw(float dt)
|
||||
{
|
||||
static std::mutex mutex;
|
||||
static float rec_timer = 0.f;
|
||||
static float reload_timer = 0.f;
|
||||
|
||||
// avoid multiple threads to update the scene
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
static std::mutex m;
|
||||
std::lock_guard<std::mutex> _lock(m);
|
||||
|
||||
// update offscreen stuff
|
||||
if (canvas && canvas->m_canvas)
|
||||
canvas->m_canvas->stroke_draw();
|
||||
|
||||
auto observer = std::bind(&App::update_ui_observer, this, std::placeholders::_1);
|
||||
|
||||
if (vr_active && ui_visible)
|
||||
{
|
||||
uirtt.bindFramebuffer();
|
||||
uirtt.clear();
|
||||
glViewport(0, 0, uirtt.getWidth(), uirtt.getHeight());
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
for (int i = 1; i < layout[main_id]->m_children.size(); i++)
|
||||
layout[main_id]->m_children[i]->watch(observer);
|
||||
//msgbox->watch(observer);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
uirtt.unbindFramebuffer();
|
||||
}
|
||||
|
||||
if (!vr_only)
|
||||
{
|
||||
#if __IOS__
|
||||
[ios_view->glview bindDrawable];
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
glViewport(off_x, off_y, (GLsizei)width, (GLsizei)height);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
for (int i = 0; i < layout[main_id]->m_children.size(); i++)
|
||||
layout[main_id]->m_children[i]->watch(observer);
|
||||
//msgbox->watch(observer);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
if (rec_running)
|
||||
{
|
||||
static float rec_timer = 0.f;
|
||||
rec_timer += dt;
|
||||
if (rec_timer > 1.f && canvas->m_canvas->m_dirty_stroke)
|
||||
{
|
||||
canvas->m_canvas->m_dirty_stroke = false;
|
||||
|
||||
LOG("rec tick");
|
||||
rec_timer = 0.f;
|
||||
|
||||
auto data = new uint8_t[width * height * 4];
|
||||
#if __IOS__
|
||||
[ios_view->glview bindDrawable];
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
|
||||
GLint dfbo, rfbo;
|
||||
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &rfbo);
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &dfbo);
|
||||
if (dfbo != rfbo)
|
||||
LOG("DIFFERENT FB");
|
||||
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(rec_mutex);
|
||||
rec_frames.emplace_back(data);
|
||||
rec_cv.notify_all();
|
||||
}
|
||||
update_rec_frames();
|
||||
}
|
||||
}
|
||||
|
||||
redraw = false;
|
||||
}
|
||||
|
||||
void App::update(float dt)
|
||||
{
|
||||
static std::mutex mutex;
|
||||
static float reload_timer = 0.f;
|
||||
|
||||
// avoid multiple threads to update the scene
|
||||
//std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
if (!(redraw || animate))
|
||||
return;
|
||||
|
||||
@@ -620,71 +685,6 @@ void App::update(float dt)
|
||||
layout[main_id]->find<NodeButtonCustom>("btn-mask-line")->set_active(mode == kCanvasMode::MaskLine);
|
||||
layout[main_id]->find<NodeButtonCustom>("btn-bucket")->set_active(mode == kCanvasMode::FloodFill);
|
||||
}
|
||||
|
||||
auto observer = std::bind(&App::update_ui_observer, this, std::placeholders::_1);
|
||||
|
||||
if (vr_active && ui_visible)
|
||||
{
|
||||
uirtt.bindFramebuffer();
|
||||
uirtt.clear();
|
||||
glViewport(0, 0, uirtt.getWidth(), uirtt.getHeight());
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
for (int i = 1; i < layout[main_id]->m_children.size(); i++)
|
||||
layout[main_id]->m_children[i]->watch(observer);
|
||||
//msgbox->watch(observer);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
uirtt.unbindFramebuffer();
|
||||
}
|
||||
|
||||
if (!vr_only)
|
||||
{
|
||||
#if __IOS__
|
||||
[ios_view->glview bindDrawable];
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
glViewport(off_x, off_y, (GLsizei)width, (GLsizei)height);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
for (int i = 0; i < layout[main_id]->m_children.size(); i++)
|
||||
layout[main_id]->m_children[i]->watch(observer);
|
||||
//msgbox->watch(observer);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
if (rec_running)
|
||||
{
|
||||
rec_timer += dt;
|
||||
if (rec_timer > 1.f && canvas->m_canvas->m_dirty_stroke)
|
||||
{
|
||||
canvas->m_canvas->m_dirty_stroke = false;
|
||||
|
||||
LOG("rec tick");
|
||||
rec_timer = 0.f;
|
||||
|
||||
auto data = new uint8_t[width * height * 4];
|
||||
#if __IOS__
|
||||
[ios_view->glview bindDrawable];
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
|
||||
GLint dfbo, rfbo;
|
||||
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &rfbo);
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &dfbo);
|
||||
if (dfbo != rfbo)
|
||||
LOG("DIFFERENT FB");
|
||||
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(rec_mutex);
|
||||
rec_frames.emplace_back(data);
|
||||
rec_cv.notify_all();
|
||||
}
|
||||
update_rec_frames();
|
||||
}
|
||||
}
|
||||
|
||||
redraw = false;
|
||||
}
|
||||
|
||||
void App::terminate()
|
||||
@@ -803,9 +803,7 @@ void App::rec_stop()
|
||||
rec_cv.notify_all();
|
||||
if (rec_thread.joinable())
|
||||
rec_thread.join();
|
||||
async_start();
|
||||
update_rec_frames();
|
||||
async_end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -821,7 +819,6 @@ void App::rec_export(std::string path)
|
||||
auto pb = layout[main_id]->add_child<NodeProgressBar>();
|
||||
pb->m_progress->SetWidthP(0);
|
||||
pb->m_title->set_text("Exporting MP4 movie");
|
||||
async_update();
|
||||
|
||||
#if defined(__IOS__) || defined(__OSX__)
|
||||
NSString* mov_path = [NSString stringWithFormat:@"%s/out.mp4", rec_path.c_str()];
|
||||
@@ -978,8 +975,6 @@ void App::rec_export(std::string path)
|
||||
#endif
|
||||
|
||||
pb->destroy();
|
||||
async_update();
|
||||
|
||||
}
|
||||
|
||||
void App::rec_loop()
|
||||
|
||||
@@ -165,6 +165,7 @@ public:
|
||||
void terminate();
|
||||
void clear();
|
||||
void tick(float dt);
|
||||
void draw(float dt);
|
||||
void update(float dt);
|
||||
bool update_ui_observer(Node* n);
|
||||
bool vr_start();
|
||||
|
||||
@@ -22,24 +22,18 @@ void App::cloud_upload()
|
||||
{
|
||||
auto upload_thread = [this] {
|
||||
BT_SetTerminate();
|
||||
|
||||
if (Canvas::I->m_unsaved)
|
||||
{
|
||||
Canvas::I->project_save_thread(doc_path);
|
||||
}
|
||||
|
||||
async_start();
|
||||
auto pb = show_progress("Uploading");
|
||||
async_redraw();
|
||||
async_end();
|
||||
|
||||
upload(doc_path, doc_filename, [this,pb](float p){
|
||||
async_start();
|
||||
pb->m_progress->SetWidthP(p * 100.f);
|
||||
async_redraw();
|
||||
async_end();
|
||||
});
|
||||
|
||||
async_start();
|
||||
pb->destroy();
|
||||
auto msgbox = new NodeMessageBox();
|
||||
msgbox->m_manager = &layout;
|
||||
@@ -48,8 +42,6 @@ void App::cloud_upload()
|
||||
msgbox->m_message->set_text("This document has been succesfully uploaded.");
|
||||
layout[main_id]->add_child(msgbox);
|
||||
layout[main_id]->update();
|
||||
async_redraw();
|
||||
async_end();
|
||||
};
|
||||
|
||||
auto m = layout[main_id]->add_child<NodeMessageBox>();
|
||||
@@ -59,14 +51,10 @@ void App::cloud_upload()
|
||||
m->btn_cancel->m_text->set_text("No");
|
||||
m->btn_ok->on_click = [this, m, upload_thread](Node*) {
|
||||
std::thread(upload_thread).detach();
|
||||
async_start();
|
||||
m->destroy();
|
||||
async_end();
|
||||
};
|
||||
m->btn_cancel->on_click = [this, m, upload_thread](Node*) {
|
||||
async_start();
|
||||
m->destroy();
|
||||
async_end();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -76,16 +64,14 @@ void App::cloud_upload_all()
|
||||
{
|
||||
std::thread([this] {
|
||||
BT_SetTerminate();
|
||||
|
||||
auto names = Asset::list_files(data_path, ".*\\.ppi");
|
||||
|
||||
gl_state gl;
|
||||
std::shared_ptr<NodeProgressBar> pb;
|
||||
if (layout.m_loaded)
|
||||
{
|
||||
async_start();
|
||||
pb = show_progress("Export Pano Image");
|
||||
async_redraw();
|
||||
async_end();
|
||||
}
|
||||
|
||||
int progress = 0;
|
||||
@@ -102,21 +88,13 @@ void App::cloud_upload_all()
|
||||
|
||||
if (layout.m_loaded)
|
||||
{
|
||||
async_start();
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
async_redraw();
|
||||
gl.restore();
|
||||
async_end();
|
||||
}
|
||||
}
|
||||
|
||||
if (layout.m_loaded)
|
||||
{
|
||||
async_start();
|
||||
pb->destroy();
|
||||
async_redraw();
|
||||
async_end();
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
@@ -143,38 +121,28 @@ void App::cloud_browse()
|
||||
dialog->destroy();
|
||||
std::thread([this, dialog] {
|
||||
BT_SetTerminate();
|
||||
async_start();
|
||||
|
||||
auto* m = layout[main_id]->add_child<NodeMessageBox>();
|
||||
m->m_title->set_text("Downloading");
|
||||
m->m_message->set_text("Download in progress");
|
||||
async_redraw();
|
||||
async_end();
|
||||
std::string url = "https://panopainter.com/cloud/cloud-dwl.php?file=" + dialog->selected_file;
|
||||
download(url, dialog->selected_path, [this,m](float p){
|
||||
static char progress[256];
|
||||
sprintf(progress, "Download in progress %.2f%%", p * 100.f);
|
||||
async_start();
|
||||
m->m_message->set_text(progress);
|
||||
async_redraw();
|
||||
async_end();
|
||||
});
|
||||
|
||||
async_start();
|
||||
canvas->reset_camera();
|
||||
layers->clear();
|
||||
async_end();
|
||||
|
||||
canvas->m_canvas->project_open_thread(dialog->selected_path);
|
||||
|
||||
async_start();
|
||||
doc_name = dialog->selected_name;
|
||||
title_update();
|
||||
for (auto& l : canvas->m_canvas->m_layers)
|
||||
layers->add_layer(l->m_name.c_str(), false);
|
||||
ActionManager::clear();
|
||||
m->destroy();
|
||||
async_redraw();
|
||||
async_end();
|
||||
}).detach();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1099,6 +1099,8 @@ void App::brush_update()
|
||||
{
|
||||
// brushes->select_brush(canvas->m_brush->id);
|
||||
// stroke->set_params(canvas->m_brush);
|
||||
render_task_async([this]
|
||||
{
|
||||
stroke->update_controls();
|
||||
quick->m_slider_flow->set_value(stroke->m_tip_flow->get_value());
|
||||
quick->m_slider_size->set_value(stroke->m_tip_size->get_value());
|
||||
@@ -1109,6 +1111,7 @@ void App::brush_update()
|
||||
floating_picker->set_color(Canvas::I->m_current_brush->m_tip_color);
|
||||
if (floating_color)
|
||||
floating_color->set_color(Canvas::I->m_current_brush->m_tip_color);
|
||||
});
|
||||
}
|
||||
|
||||
void App::init_menu_layer()
|
||||
|
||||
292
src/canvas.cpp
292
src/canvas.cpp
@@ -179,6 +179,8 @@ void Canvas::stroke_cancel()
|
||||
}
|
||||
void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
|
||||
gl_state gl;
|
||||
gl.save();
|
||||
|
||||
@@ -321,6 +323,8 @@ std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vert
|
||||
|
||||
glm::vec4 Canvas::stroke_draw_samples(int i, std::vector<vertex_t>& P)
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
@@ -454,6 +458,8 @@ std::vector<Canvas::StrokeFrame> Canvas::stroke_draw_compute(Stroke& stroke) con
|
||||
|
||||
void Canvas::stroke_draw()
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
|
||||
if (!(m_current_stroke && m_current_stroke->has_sample()))
|
||||
{
|
||||
//stroke_draw_mix({ 0,0 }, { m_mixer.getWidth(), m_mixer.getHeight() });
|
||||
@@ -690,6 +696,8 @@ glm::vec3 Canvas::point_trace(glm::vec2 loc)
|
||||
}
|
||||
void Canvas::stroke_commit()
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
|
||||
if (!m_dirty || m_layers.empty())
|
||||
return;
|
||||
|
||||
@@ -866,8 +874,8 @@ void Canvas::stroke_commit()
|
||||
|
||||
void Canvas::draw_merge(std::array<bool, 6> faces /*= SIXPLETTE(false)*/)
|
||||
{
|
||||
gl_state gl;
|
||||
gl.save();
|
||||
assert(App::I.is_render_thread());
|
||||
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
auto ortho = glm::ortho<float>(-0.5f, 0.5f, -0.5f, 0.5f, -1.f, 1.f);
|
||||
const auto& b = m_current_stroke->m_brush;
|
||||
@@ -1112,8 +1120,6 @@ void Canvas::draw_merge(std::array<bool, 6> faces /*= SIXPLETTE(false)*/)
|
||||
|
||||
m_layers_merge.m_rtt[plane_index].unbindFramebuffer();
|
||||
}
|
||||
|
||||
gl.restore();
|
||||
}
|
||||
|
||||
void Canvas::stroke_update(glm::vec3 point, float pressure)
|
||||
@@ -1124,6 +1130,8 @@ void Canvas::stroke_update(glm::vec3 point, float pressure)
|
||||
}
|
||||
void Canvas::stroke_start(glm::vec3 point, float pressure)
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
|
||||
// need to commit this now before starting a new stroke
|
||||
if (m_current_stroke && m_commit_delayed)
|
||||
{
|
||||
@@ -1221,16 +1229,8 @@ void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
|
||||
{
|
||||
m_dirty = false;
|
||||
|
||||
// save viewport and clear color states
|
||||
GLint vp[4];
|
||||
GLfloat cc[4];
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
GLboolean blend = glIsEnabled(GL_BLEND);
|
||||
|
||||
// allocate action to add to history
|
||||
auto action = new ActionStroke;
|
||||
|
||||
App::I.render_task([&]
|
||||
{
|
||||
// prepare common states
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
glDisable(GL_BLEND);
|
||||
@@ -1242,17 +1242,6 @@ void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
|
||||
|
||||
m_layers[dest_idx]->m_rtt[i].bindFramebuffer();
|
||||
|
||||
/*
|
||||
// save image before commit
|
||||
glm::vec2 box_sz = m_dirty_box[i].zw() - m_dirty_box[i].xy();
|
||||
action->m_image[i] = std::make_unique<uint8_t[]>(box_sz.x * box_sz.y * 4);
|
||||
glReadPixels(m_dirty_box[i].x, m_dirty_box[i].y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, action->m_image[i].get());
|
||||
|
||||
action->m_box[i] = m_dirty_box[i];
|
||||
action->m_old_box[i] = m_layers[m_current_layer_idx]->m_dirty_box[i];
|
||||
action->m_old_dirty[i] = m_layers[m_current_layer_idx]->m_dirty_face[i];
|
||||
*/
|
||||
|
||||
auto& lbox = m_layers[dest_idx]->m_dirty_box[i];
|
||||
lbox = glm::vec4(
|
||||
glm::min(xy(m_layers[source_idx]->m_dirty_box[i]), xy(lbox)),
|
||||
@@ -1294,20 +1283,7 @@ void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
|
||||
|
||||
m_layers[dest_idx]->m_rtt[i].unbindFramebuffer();
|
||||
}
|
||||
|
||||
// restore viewport and clear color states
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
/*
|
||||
// save history
|
||||
action->m_layer_idx = m_current_layer_idx;
|
||||
action->m_canvas = this;
|
||||
action->m_stroke = std::move(m_current_stroke);
|
||||
ActionManager::add(action);
|
||||
*/
|
||||
});
|
||||
}
|
||||
|
||||
void Canvas::flood_fill(int layer, int plane, std::vector<glm::ivec2> pos, FloodData& plane_data,
|
||||
@@ -1611,26 +1587,25 @@ void Canvas::clear_context()
|
||||
|
||||
void Canvas::import_equirectangular(std::string file_path, std::shared_ptr<Layer> layer /*= nullptr*/)
|
||||
{
|
||||
std::thread t(&Canvas::import_equirectangular_thread, this, file_path, layer);
|
||||
if (App::I.check_license())
|
||||
{
|
||||
std::thread t([=] {
|
||||
BT_SetTerminate();
|
||||
import_equirectangular_thread(file_path, layer);
|
||||
});
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::import_equirectangular_thread(std::string file_path, std::shared_ptr<Layer> layer /*= nullptr*/)
|
||||
{
|
||||
BT_SetTerminate();
|
||||
|
||||
Image img;
|
||||
if (!img.load_file(file_path))
|
||||
return;
|
||||
|
||||
App::I.async_start();
|
||||
|
||||
if (!layer)
|
||||
layer = m_layers[m_current_layer_idx];
|
||||
|
||||
gl_state gl;
|
||||
gl.save();
|
||||
|
||||
auto a = new ActionImportEquirect;
|
||||
a->m_layer = layer;
|
||||
a->m_snap = std::make_shared<Layer::Snapshot>(layer->snapshot());
|
||||
@@ -1642,14 +1617,15 @@ void Canvas::import_equirectangular_thread(std::string file_path, std::shared_pt
|
||||
if (img.width == img.height / 6)
|
||||
{
|
||||
Texture2D tex;
|
||||
static GLint indices[] = { 5, 0, 4, 1, 2, 3 };
|
||||
static GLint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA };
|
||||
static GLint iformats[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 };
|
||||
static const GLint indices[] = { 5, 0, 4, 1, 2, 3 };
|
||||
static const GLint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA };
|
||||
static const GLint iformats[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 };
|
||||
tex.create(img.width, img.width, iformats[img.comp - 1], formats[img.comp - 1]);
|
||||
int stride = img.width * img.width * img.comp;
|
||||
Plane plane;
|
||||
plane.create<1>(2, 2);
|
||||
draw_objects([&](const glm::mat4& camera, const glm::mat4& proj, int i) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
tex.update(img.m_data.get() + indices[i] * stride);
|
||||
m_sampler.bind(0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
@@ -1661,15 +1637,16 @@ void Canvas::import_equirectangular_thread(std::string file_path, std::shared_pt
|
||||
tex.unbind();
|
||||
m_sampler.unbind();
|
||||
});
|
||||
plane.destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
Texture2D tex;
|
||||
tex.load_file(file_path);
|
||||
Sphere sphere;
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
sphere.create<64, 64>(2.f);
|
||||
draw_objects([&](const glm::mat4& camera, const glm::mat4& proj, int i) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
m_sampler.bind(0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
tex.bind();
|
||||
@@ -1681,15 +1658,13 @@ void Canvas::import_equirectangular_thread(std::string file_path, std::shared_pt
|
||||
tex.unbind();
|
||||
m_sampler.unbind();
|
||||
});
|
||||
sphere.destroy();
|
||||
}
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
layer->m_dirty_box[i] = glm::vec4(0, 0, m_width, m_height);
|
||||
layer->m_dirty_face[i] = true;
|
||||
}
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
App::I.async_end();
|
||||
}
|
||||
|
||||
void Canvas::export_equirectangular(std::string file_path, std::function<void()> on_complete)
|
||||
@@ -1708,10 +1683,6 @@ void Canvas::export_equirectangular(std::string file_path, std::function<void()>
|
||||
|
||||
void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
{
|
||||
gl_state gl;
|
||||
|
||||
App::I.async_start();
|
||||
|
||||
std::shared_ptr<NodeProgressBar> pb;
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
@@ -1723,28 +1694,12 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
pb->m_progress->SetWidthP(0);
|
||||
pb->m_title->set_text("Export Pano Image");
|
||||
App::I.layout[App::I.main_id]->add_child(pb);
|
||||
App::I.async_update();
|
||||
}
|
||||
|
||||
// save viewport and clear color states
|
||||
GLint vp[4];
|
||||
GLfloat cc[4];
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
GLboolean blend = glIsEnabled(GL_BLEND);
|
||||
|
||||
// prepare common states
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
RTT m_latlong;
|
||||
m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense
|
||||
|
||||
GLuint cube_id;
|
||||
glGenTextures(1, &cube_id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
|
||||
for (GLuint i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
static int faces[]{
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, // front
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // right
|
||||
@@ -1754,6 +1709,17 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // bottom
|
||||
};
|
||||
|
||||
App::I.render_task([&]
|
||||
{
|
||||
glGenTextures(1, &cube_id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
|
||||
for (GLuint i = 0; i < 6; i++)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8,
|
||||
m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
}
|
||||
});
|
||||
|
||||
int progress = 0;
|
||||
int total = 6 + 2;
|
||||
|
||||
@@ -1761,6 +1727,8 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
face.create(m_width, m_height);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
App::I.render_task([&]
|
||||
{
|
||||
// prepare common states
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
@@ -1833,6 +1801,7 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
|
||||
m_tmp[i].unbindFramebuffer();
|
||||
});
|
||||
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
@@ -1841,9 +1810,6 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1859,6 +1825,8 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
// int ret = stbi_write_png(name, m_tmp[i].getWidth(), m_tmp[i].getHeight(), 4, data.get(), m_tmp[i].stride());
|
||||
//}
|
||||
|
||||
App::I.render_task([&]
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
@@ -1872,22 +1840,17 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
m_sampler_mask.unbind();
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
m_latlong.unbindFramebuffer();
|
||||
{
|
||||
});
|
||||
|
||||
auto latlong_data = std::make_unique<uint8_t[]>(m_latlong.bytes());
|
||||
m_latlong.readTextureData(latlong_data.get());
|
||||
|
||||
{
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
LOG("progress: %f", p);
|
||||
LOG("progress: %f", (float)progress / total * 100.f);
|
||||
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
}
|
||||
pb->m_progress->SetWidthP((float)progress / total * 100.f);
|
||||
}
|
||||
|
||||
LOG("writing %s", file_path.c_str());
|
||||
@@ -1901,18 +1864,12 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
stbi_write_png(file_path.c_str(), m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
LOG("progress: %f", p);
|
||||
LOG("progress: %f", (float)progress / total * 100.f);
|
||||
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
}
|
||||
pb->m_progress->SetWidthP((float)progress / total * 100.f);
|
||||
}
|
||||
|
||||
//int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
||||
@@ -1930,23 +1887,17 @@ void Canvas::export_equirectangular_thread(std::string file_path)
|
||||
}
|
||||
}];
|
||||
#endif
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &cube_id);
|
||||
App::I.render_task_async([id=cube_id]
|
||||
{
|
||||
glDeleteTextures(1, &id);
|
||||
});
|
||||
m_latlong.destroy();
|
||||
|
||||
// restore viewport and clear color states
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->destroy();
|
||||
App::I.async_update();
|
||||
}
|
||||
App::I.async_end();
|
||||
}
|
||||
|
||||
void Canvas::inject_xmp(std::string jpg_path)
|
||||
@@ -2002,7 +1953,6 @@ void Canvas::export_depth(std::string file_name, std::function<void()> on_comple
|
||||
if (App::I.check_license())
|
||||
{
|
||||
std::thread t([=] {
|
||||
BT_SetTerminate();
|
||||
export_depth_thread(file_name);
|
||||
if (on_complete)
|
||||
on_complete();
|
||||
@@ -2013,24 +1963,21 @@ void Canvas::export_depth(std::string file_name, std::function<void()> on_comple
|
||||
|
||||
void Canvas::export_depth_thread(std::string file_name)
|
||||
{
|
||||
App::I.async_start();
|
||||
gl_state gl;
|
||||
gl.save();
|
||||
|
||||
draw_merge();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
RTT rtt;
|
||||
rtt.create(1024, 1024);
|
||||
rtt.bindFramebuffer();
|
||||
rtt.clear({ 0, 0, 0, 1 });
|
||||
|
||||
glViewport(0, 0, rtt.getWidth(), rtt.getHeight());
|
||||
glm::mat4 proj = glm::perspective(glm::radians(m_cam_fov), (float)rtt.getWidth() / (float)rtt.getHeight(), 0.1f, 100.f);
|
||||
glm::mat4 camera = m_cam_rot;
|
||||
|
||||
App::I.render_task([&]
|
||||
{
|
||||
draw_merge();
|
||||
|
||||
rtt.bindFramebuffer();
|
||||
rtt.clear({ 0, 0, 0, 1 });
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, rtt.getWidth(), rtt.getHeight());
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
auto plane_mvp_z = proj * camera *
|
||||
@@ -2059,6 +2006,8 @@ void Canvas::export_depth_thread(std::string file_name)
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_layers_merge.m_rtt[plane_index].unbindTexture();
|
||||
}
|
||||
rtt.unbindFramebuffer();
|
||||
});
|
||||
|
||||
uint8_t* rgba_data = rtt.readTextureData();
|
||||
stbi_flip_vertically_on_write(true);
|
||||
@@ -2066,7 +2015,13 @@ void Canvas::export_depth_thread(std::string file_name)
|
||||
stbi_write_jpg(path_rgba.c_str(), rtt.getWidth(), rtt.getHeight(), 4, rgba_data, 100);
|
||||
delete rgba_data;
|
||||
|
||||
App::I.render_task([&]
|
||||
{
|
||||
rtt.bindFramebuffer();
|
||||
rtt.clear({ 0, 0, 0, 1 });
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, rtt.getWidth(), rtt.getHeight());
|
||||
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
|
||||
{
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
@@ -2094,6 +2049,8 @@ void Canvas::export_depth_thread(std::string file_name)
|
||||
m_layers[layer_index]->m_rtt[plane_index].unbindTexture();
|
||||
}
|
||||
}
|
||||
rtt.unbindFramebuffer();
|
||||
});
|
||||
|
||||
uint8_t* depth_data = rtt.readTextureData();
|
||||
std::string path_depth = App::I.work_path + "/" + file_name + "_depth.png";
|
||||
@@ -2101,11 +2058,7 @@ void Canvas::export_depth_thread(std::string file_name)
|
||||
delete depth_data;
|
||||
stbi_flip_vertically_on_write(false);
|
||||
|
||||
rtt.unbindFramebuffer();
|
||||
rtt.destroy();
|
||||
|
||||
gl.restore();
|
||||
App::I.async_end();
|
||||
}
|
||||
|
||||
void Canvas::export_layers(std::string file_name, std::function<void()> on_complete)
|
||||
@@ -2124,16 +2077,6 @@ void Canvas::export_layers(std::string file_name, std::function<void()> on_compl
|
||||
|
||||
void Canvas::export_layers_thread(std::string file_name)
|
||||
{
|
||||
App::I.async_start();
|
||||
|
||||
// save viewport and clear color states
|
||||
GLint vp[4];
|
||||
GLfloat cc[4];
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
GLboolean blend = glIsEnabled(GL_BLEND);
|
||||
|
||||
gl_state gl;
|
||||
std::shared_ptr<NodeProgressBar> pb;
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
@@ -2145,22 +2088,14 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
pb->m_progress->SetWidthP(0);
|
||||
pb->m_title->set_text("Export Pano Layers");
|
||||
App::I.layout[App::I.main_id]->add_child(pb);
|
||||
App::I.async_update();
|
||||
}
|
||||
int progress = 0;
|
||||
int total = (int)(m_layers.size() + 1) * 6;
|
||||
|
||||
// prepare common states
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
|
||||
RTT m_latlong;
|
||||
m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense
|
||||
|
||||
GLuint cube_id;
|
||||
glGenTextures(1, &cube_id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
|
||||
for (GLuint i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
int faces[]{
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, // front
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // right
|
||||
@@ -2169,14 +2104,23 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // top
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // bottom
|
||||
};
|
||||
App::I.render_task([&]
|
||||
{
|
||||
glGenTextures(1, &cube_id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
|
||||
for (GLuint i = 0; i < 6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
});
|
||||
|
||||
int seq = 0;
|
||||
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
|
||||
{
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
App::I.render_task([&]
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
m_tmp[i].bindFramebuffer();
|
||||
|
||||
//if (seq == 0)
|
||||
@@ -2212,6 +2156,7 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
|
||||
m_tmp[i].unbindFramebuffer();
|
||||
});
|
||||
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
@@ -2220,13 +2165,11 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
App::I.render_task([&]
|
||||
{
|
||||
glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_latlong.bindFramebuffer();
|
||||
@@ -2241,6 +2184,8 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
m_sampler_mask.unbind();
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
m_latlong.unbindFramebuffer();
|
||||
});
|
||||
|
||||
{
|
||||
auto latlong_data = std::make_unique<uint8_t[]>(m_latlong.bytes());
|
||||
m_latlong.readTextureData(latlong_data.get());
|
||||
@@ -2248,9 +2193,7 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
sprintf(name, "%s/%s-layer-%02d.png", App::I.work_path.c_str(), file_name.c_str(), seq);
|
||||
seq++;
|
||||
LOG("writing %s", name);
|
||||
App::I.async_end();
|
||||
int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
|
||||
App::I.async_start();
|
||||
}
|
||||
|
||||
progress++;
|
||||
@@ -2260,28 +2203,19 @@ void Canvas::export_layers_thread(std::string file_name)
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
}
|
||||
}
|
||||
|
||||
App::I.render_task([&]
|
||||
{
|
||||
glDeleteTextures(1, &cube_id);
|
||||
m_latlong.destroy();
|
||||
});
|
||||
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
pb->destroy();
|
||||
App::I.async_update();
|
||||
}
|
||||
|
||||
// restore viewport and clear color states
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
App::I.async_end();
|
||||
}
|
||||
|
||||
void Canvas::export_cubes()
|
||||
@@ -2401,8 +2335,6 @@ void Canvas::project_save(std::string file_path, std::function<void(bool)> on_co
|
||||
|
||||
bool Canvas::project_save_thread(std::string file_path)
|
||||
{
|
||||
gl_state gl;
|
||||
|
||||
// already saved, nothing to do
|
||||
if (!m_unsaved && file_path == App::I.doc_path)
|
||||
{
|
||||
@@ -2453,7 +2385,6 @@ bool Canvas::project_save_thread(std::string file_path)
|
||||
fwrite(&ppi_header, sizeof(PPIHeader), 1, fp);
|
||||
|
||||
// load thumbnail
|
||||
App::I.async_start();
|
||||
Image thumb = thumbnail_generate(ppi_header.thumb_header.width, ppi_header.thumb_header.height);
|
||||
auto pb = std::make_shared<NodeProgressBar>();
|
||||
pb->m_manager = &App::I.layout;
|
||||
@@ -2463,8 +2394,6 @@ bool Canvas::project_save_thread(std::string file_path)
|
||||
pb->m_progress->SetWidthP(0);
|
||||
pb->m_title->set_text("Saving Pano Project");
|
||||
App::I.layout[App::I.main_id]->add_child(pb);
|
||||
App::I.async_update();
|
||||
App::I.async_end();
|
||||
|
||||
thumb.flip();
|
||||
fwrite(thumb.data(), thumb.size(), 1, fp);
|
||||
@@ -2497,10 +2426,7 @@ bool Canvas::project_save_thread(std::string file_path)
|
||||
fwrite(&m_layers[i]->m_visible, sizeof(bool), 1, fp);
|
||||
}
|
||||
|
||||
App::I.async_start();
|
||||
auto snap = m_layers[i]->snapshot();
|
||||
App::I.async_update();
|
||||
App::I.async_end();
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
int has_data = snap.m_dirty_face[plane_index] ? 1 : 0;
|
||||
@@ -2527,11 +2453,8 @@ bool Canvas::project_save_thread(std::string file_path)
|
||||
}
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
App::I.async_start();
|
||||
pb->m_progress->SetWidthP(p);
|
||||
LOG("progress: %f", p);
|
||||
App::I.async_update();
|
||||
App::I.async_end();
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
@@ -2571,11 +2494,8 @@ bool Canvas::project_save_thread(std::string file_path)
|
||||
m_newdoc = false;
|
||||
}
|
||||
|
||||
App::I.async_start();
|
||||
pb->destroy();
|
||||
App::I.title_update();
|
||||
App::I.async_update();
|
||||
App::I.async_end();
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -2609,11 +2529,9 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
return false;
|
||||
}
|
||||
|
||||
gl_state gl;
|
||||
std::shared_ptr<NodeProgressBar> pb;
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
App::I.async_start();
|
||||
pb = std::make_shared<NodeProgressBar>();
|
||||
pb->m_manager = &App::I.layout;
|
||||
pb->init();
|
||||
@@ -2622,10 +2540,6 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
pb->m_progress->SetWidthP(0);
|
||||
pb->m_title->set_text("Opening Pano Project");
|
||||
App::I.layout[App::I.main_id]->add_child(pb);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
App::I.async_end();
|
||||
}
|
||||
|
||||
// skip thumbnail
|
||||
@@ -2648,13 +2562,11 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
int progress = 0;
|
||||
int total = n_layers * 6;
|
||||
|
||||
App::I.async_start();
|
||||
for (auto& l : m_layers)
|
||||
l->destroy();
|
||||
m_layers.clear();
|
||||
//clear_all();
|
||||
resize(m_width, m_height);
|
||||
App::I.async_end();
|
||||
|
||||
std::vector<std::shared_ptr<Layer>> tmp_layers(n_layers);
|
||||
|
||||
@@ -2713,20 +2625,12 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
App::I.async_start();
|
||||
pb->m_progress->SetWidthP(p);
|
||||
gl.save();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
App::I.async_end();
|
||||
}
|
||||
}
|
||||
|
||||
App::I.async_start();
|
||||
layer->create(m_width, m_height, name.c_str());
|
||||
layer->clear({ 0, 0, 0, 0 });
|
||||
layer->restore(snap);
|
||||
App::I.async_end();
|
||||
}
|
||||
|
||||
std::swap(tmp_layers, m_layers);
|
||||
@@ -2749,20 +2653,8 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
m_newdoc = false;
|
||||
if (App::I.layout.m_loaded)
|
||||
{
|
||||
App::I.async_start();
|
||||
pb->destroy();
|
||||
gl.save();
|
||||
draw_merge();
|
||||
App::I.async_update();
|
||||
gl.restore();
|
||||
App::I.title_update();
|
||||
App::I.async_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
App::I.async_start();
|
||||
draw_merge();
|
||||
App::I.async_end();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,10 +33,13 @@ void ActionStroke::undo()
|
||||
|
||||
glm::vec2 box_sz = zw(m_box[i]) - xy(m_box[i]);
|
||||
if (box_sz.x > 0 && box_sz.y > 0 && box_sz.x <= m_canvas->m_layers[m_layer_idx]->w && box_sz.y <= m_canvas->m_layers[m_layer_idx]->h)
|
||||
{
|
||||
App::I.render_task([&]
|
||||
{
|
||||
m_canvas->m_layers[m_layer_idx]->m_rtt[i].bindTexture();
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, (int)m_box[i].x, (int)m_box[i].y, (int)box_sz.x, (int)box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, m_image[i].get());
|
||||
m_canvas->m_layers[m_layer_idx]->m_rtt[i].unbindTexture();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -66,7 +69,6 @@ Action* ActionStroke::get_redo()
|
||||
if (!layer->m_dirty_face[i] && !m_image[i])
|
||||
continue; // no stroke on this face, skip it
|
||||
|
||||
layer->m_rtt[i].bindFramebuffer();
|
||||
|
||||
auto box = clear_layer ? glm::ivec4(layer->m_dirty_box[i]) : m_box[i];
|
||||
|
||||
@@ -76,7 +78,12 @@ Action* ActionStroke::get_redo()
|
||||
if (box_sz.x > 0 && box_sz.y > 0 && box_sz.x <= layer->w && box_sz.y <= layer->h)
|
||||
{
|
||||
action->m_image[i] = std::make_unique<uint8_t[]>(box_sz.x * box_sz.y * 4);
|
||||
App::I.render_task([&]
|
||||
{
|
||||
layer->m_rtt[i].bindFramebuffer();
|
||||
glReadPixels(box_or.x, box_or.y, box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, action->m_image[i].get());
|
||||
layer->m_rtt[i].unbindFramebuffer();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -86,8 +93,6 @@ Action* ActionStroke::get_redo()
|
||||
action->m_box[i] = box;
|
||||
action->m_old_box[i] = layer->m_dirty_box[i];
|
||||
action->m_old_dirty[i] = layer->m_dirty_face[i];
|
||||
|
||||
layer->m_rtt[i].unbindFramebuffer();
|
||||
}
|
||||
// save history
|
||||
action->m_layer_idx = m_layer_idx;
|
||||
|
||||
@@ -135,7 +135,10 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
}
|
||||
else
|
||||
{
|
||||
Canvas::I->stroke_start({ loc, 0 }, me->m_pressure);
|
||||
App::I.render_task_async([loc, pr=me->m_pressure]
|
||||
{
|
||||
Canvas::I->stroke_start({ loc, 0 }, pr);
|
||||
});
|
||||
}
|
||||
m_dragging = true;
|
||||
node->mouse_capture();
|
||||
@@ -144,7 +147,10 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
if (m_dragging && !m_picking)
|
||||
{
|
||||
node->mouse_release();
|
||||
App::I.render_task_async([]
|
||||
{
|
||||
Canvas::I->stroke_end();
|
||||
});
|
||||
}
|
||||
if (m_dragging && m_picking)
|
||||
{
|
||||
@@ -178,7 +184,12 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
if (m_dragging && !m_picking && !m_resizing)
|
||||
Canvas::I->stroke_update({ loc, 0 }, me->m_pressure);
|
||||
{
|
||||
App::I.render_task_async([loc, pr=me->m_pressure]
|
||||
{
|
||||
Canvas::I->stroke_update({ loc, 0 }, pr);
|
||||
});
|
||||
}
|
||||
if (m_dragging && m_picking)
|
||||
{
|
||||
glm::vec4 pix = Canvas::I->pick_get(loc);
|
||||
@@ -196,8 +207,11 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
break;
|
||||
case kEventType::MouseCancel:
|
||||
if (m_dragging)
|
||||
{
|
||||
App::I.render_task_async([]
|
||||
{
|
||||
Canvas::I->stroke_cancel();
|
||||
});
|
||||
m_dragging = false;
|
||||
node->mouse_release();
|
||||
}
|
||||
@@ -298,11 +312,14 @@ void CanvasModeLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
case kEventType::MouseUpL:
|
||||
node->mouse_release();
|
||||
if (m_dragging)
|
||||
{
|
||||
App::I.render_task_async([=]
|
||||
{
|
||||
Canvas::I->stroke_start({ m_drag_start, 0 }, 1.f);
|
||||
Canvas::I->stroke_update({ m_drag_pos, 0 }, 1.f);
|
||||
Canvas::I->stroke_draw();
|
||||
Canvas::I->stroke_end();
|
||||
});
|
||||
}
|
||||
m_dragging = false;
|
||||
break;
|
||||
|
||||
34
src/main.cpp
34
src/main.cpp
@@ -811,7 +811,7 @@ void render_thread_main()
|
||||
async_lock();
|
||||
while (!working_list.empty())
|
||||
{
|
||||
//LOG("render task %d", count);
|
||||
LOG("render task %d", count);
|
||||
count++;
|
||||
working_list.front()();
|
||||
working_list.pop_front();
|
||||
@@ -1133,11 +1133,12 @@ int main(int argc, char** argv)
|
||||
|
||||
if (App::I.redraw)
|
||||
{
|
||||
App::I.update(frame_timer);
|
||||
render_task([frame_timer]
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
App::I.clear();
|
||||
App::I.update(frame_timer);
|
||||
App::I.draw(frame_timer);
|
||||
SwapBuffers(hDC);
|
||||
});
|
||||
frame_timer = 0;
|
||||
@@ -1244,39 +1245,28 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||
BT_SetTerminate();
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(task_mutex);
|
||||
tasklist.emplace_back([=] {
|
||||
if (App::I.request_close())
|
||||
{
|
||||
running = 0;
|
||||
ui_render_cv.notify_all();
|
||||
if (ui_renderer.joinable())
|
||||
ui_renderer.join();
|
||||
if (hmd_renderer.joinable())
|
||||
hmd_renderer.join();
|
||||
App::I.terminate();
|
||||
PostQuitMessage(0);
|
||||
render_running = false;
|
||||
if (render_thread.joinable())
|
||||
render_thread.join();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
destroy_window();
|
||||
}
|
||||
});
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
case WM_SIZE:
|
||||
{
|
||||
auto w = (float)LOWORD(lp);
|
||||
auto h = (float)HIWORD(lp);
|
||||
if (h != 0 && running == 1)
|
||||
{
|
||||
App::I.render_task([=]
|
||||
std::lock_guard<std::mutex> lock(task_mutex);
|
||||
tasklist.emplace_back([=]
|
||||
{
|
||||
App::I.resize(w, h);
|
||||
App::I.clear();
|
||||
App::I.redraw = true;
|
||||
App::I.update(0.f);
|
||||
SwapBuffers(hDC);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
15
src/node.cpp
15
src/node.cpp
@@ -42,21 +42,6 @@ void Node::app_redraw()
|
||||
App::I.redraw = true;
|
||||
}
|
||||
|
||||
void Node::async_start()
|
||||
{
|
||||
App::I.async_start();
|
||||
}
|
||||
|
||||
void Node::async_update()
|
||||
{
|
||||
App::I.async_update();
|
||||
}
|
||||
|
||||
void Node::async_end()
|
||||
{
|
||||
App::I.async_end();
|
||||
}
|
||||
|
||||
void Node::watch(std::function<bool(Node*)> observer)
|
||||
{
|
||||
bool cont = observer(this);
|
||||
|
||||
@@ -266,9 +266,6 @@ public:
|
||||
const Node* init_template(const char* id);
|
||||
void tick(float dt);
|
||||
void app_redraw();
|
||||
void async_start();
|
||||
void async_update();
|
||||
void async_end();
|
||||
void add_child(Node* n);
|
||||
void add_child(Node* n, int index);
|
||||
void add_child(std::shared_ptr<Node> n);
|
||||
|
||||
@@ -80,7 +80,6 @@ void NodeDialogBrowse::init_controls()
|
||||
btn_path->on_click = [this](Node*){
|
||||
App::I.pick_dir([this](std::string path){
|
||||
LOG("change working path to %s", path.c_str());
|
||||
async_start();
|
||||
App::I.work_path = path;
|
||||
#ifdef _WIN32
|
||||
GetFullPathNameA(path.c_str(), sizeof(path_buffer), path_buffer, nullptr);
|
||||
@@ -91,8 +90,6 @@ void NodeDialogBrowse::init_controls()
|
||||
search_paths = {path};
|
||||
clear_list();
|
||||
init_list();
|
||||
async_update();
|
||||
async_end();
|
||||
});
|
||||
};
|
||||
working_path = find<NodeText>("path");
|
||||
|
||||
@@ -55,7 +55,6 @@ void NodeDialogCloud::load_thumbs_thread()
|
||||
std::string res;
|
||||
if (curl)
|
||||
{
|
||||
async_start();
|
||||
auto* align = container->add_child<Node>();
|
||||
align->SetWidthP(100.f);
|
||||
align->SetHeightP(100.f);
|
||||
@@ -64,8 +63,6 @@ void NodeDialogCloud::load_thumbs_thread()
|
||||
auto* text = align->add_child<NodeText>();
|
||||
text->set_font(kFont::Arial_30);
|
||||
text->set_text("Connecting to the server...");
|
||||
async_update();
|
||||
async_end();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &res);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_data_handler);
|
||||
@@ -78,16 +75,11 @@ void NodeDialogCloud::load_thumbs_thread()
|
||||
if (err != CURLE_OK)
|
||||
{
|
||||
LOG("connection error: %d", err);
|
||||
async_start();
|
||||
text->set_text("Could not connect to the server");
|
||||
async_update();
|
||||
async_end();
|
||||
return;
|
||||
}
|
||||
|
||||
async_start();
|
||||
align->destroy();
|
||||
async_end();
|
||||
|
||||
LOG("CLOUD LIST: %s", res.c_str());
|
||||
|
||||
@@ -95,7 +87,6 @@ void NodeDialogCloud::load_thumbs_thread()
|
||||
std::vector<NodeDialogCloudItem*> nodes;
|
||||
|
||||
// create slots with name
|
||||
App::I.async_start();
|
||||
for (const auto& n : names)
|
||||
{
|
||||
auto node = new NodeDialogCloudItem;
|
||||
@@ -117,8 +108,6 @@ void NodeDialogCloud::load_thumbs_thread()
|
||||
};
|
||||
nodes.push_back(node);
|
||||
}
|
||||
App::I.async_update();
|
||||
App::I.async_end();
|
||||
|
||||
// load the icons
|
||||
for (int i = 0; i < names.size(); i++)
|
||||
@@ -149,12 +138,9 @@ void NodeDialogCloud::load_thumbs_thread()
|
||||
thumb.create(width, height);
|
||||
thumb.copy_from((uint8_t*)rgb.data());
|
||||
|
||||
App::I.async_start();
|
||||
auto image_tex = node->find<NodeImageTexture>("thumb-tex");
|
||||
image_tex->tex.destroy();
|
||||
image_tex->tex.create(thumb);
|
||||
App::I.async_update();
|
||||
App::I.async_end();
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
@@ -200,7 +200,6 @@ void NodeDialogSave::init_controls()
|
||||
btn_path->on_click = [this](Node*){
|
||||
App::I.pick_dir([this](std::string path){
|
||||
LOG("change working path to %s", path.c_str());
|
||||
async_start();
|
||||
App::I.work_path = path;
|
||||
#ifdef _WIN32
|
||||
GetFullPathNameA(path.c_str(), sizeof(path_buffer), path_buffer, nullptr);
|
||||
@@ -208,8 +207,6 @@ void NodeDialogSave::init_controls()
|
||||
realpath(path.c_str(), path_buffer);
|
||||
#endif
|
||||
working_path->set_text_format("Working dir: %s", path_buffer);
|
||||
async_update();
|
||||
async_end();
|
||||
});
|
||||
};
|
||||
working_path = find<NodeText>("path");
|
||||
@@ -264,7 +261,6 @@ void NodeDialogNewDoc::init_controls()
|
||||
btn_path->on_click = [this](Node*){
|
||||
App::I.pick_dir([this](std::string path){
|
||||
LOG("change working path to %s", path.c_str());
|
||||
async_start();
|
||||
App::I.work_path = path;
|
||||
#ifdef _WIN32
|
||||
GetFullPathNameA(path.c_str(), sizeof(path_buffer), path_buffer, nullptr);
|
||||
@@ -272,8 +268,6 @@ void NodeDialogNewDoc::init_controls()
|
||||
realpath(path.c_str(), path_buffer);
|
||||
#endif
|
||||
working_path->set_text_format("Working dir: %s", path_buffer);
|
||||
async_update();
|
||||
async_end();
|
||||
});
|
||||
};
|
||||
working_path = find<NodeText>("path");
|
||||
|
||||
@@ -102,7 +102,6 @@ void NodePanelBrush::init()
|
||||
//auto po2 = img.resize_power2();
|
||||
img.save(path_high);
|
||||
|
||||
async_start();
|
||||
NodeButtonBrush* brush = new NodeButtonBrush;
|
||||
m_container->add_child(brush);
|
||||
brush->init();
|
||||
@@ -114,8 +113,6 @@ void NodePanelBrush::init()
|
||||
brush->brush_name = name;
|
||||
brush->m_user_brush = true;
|
||||
brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
|
||||
app_redraw();
|
||||
async_end();
|
||||
save();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -78,7 +78,6 @@ void NodePanelGrid::init_controls()
|
||||
m_hm_load->on_click = [this](Node*) {
|
||||
App::I.pick_image([this](std::string path) {
|
||||
Image img;
|
||||
async_start();
|
||||
if (img.load_file(path))
|
||||
{
|
||||
m_file_path = path;
|
||||
@@ -93,8 +92,6 @@ void NodePanelGrid::init_controls()
|
||||
m_groud_opacity->set_value(1.f);
|
||||
m_rt_dirty = true;
|
||||
}
|
||||
async_update();
|
||||
async_end();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -380,7 +377,6 @@ void NodePanelGrid::bake_uvs()
|
||||
pb->m_progress->SetWidthP(0);
|
||||
pb->m_title->set_text("Lightmap Rendering");
|
||||
pb->btn_cancel->destroy();
|
||||
async_update();
|
||||
|
||||
if (m_rt_dirty)
|
||||
{
|
||||
@@ -462,7 +458,6 @@ void NodePanelGrid::bake_uvs()
|
||||
while (pb_value < fb.getHeight())
|
||||
{
|
||||
pb->m_progress->SetWidthP((float)pb_value / (float)fb.getHeight() * 100.f);
|
||||
async_update();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
worker.join();
|
||||
|
||||
@@ -42,11 +42,7 @@ bool NodePanelStroke::import_abr(const std::string& path)
|
||||
if (!str_iequals(ext, "abr") || !Asset::exist(path))
|
||||
return false;
|
||||
|
||||
async_start();
|
||||
auto pb = App::I.show_progress("Importing ABR");
|
||||
app_redraw();
|
||||
async_update();
|
||||
async_end();
|
||||
|
||||
abr.open(path);
|
||||
|
||||
@@ -68,7 +64,6 @@ bool NodePanelStroke::import_abr(const std::string& path)
|
||||
auto thumb = padded.resize(64, 64);
|
||||
thumb.save(path_thumb);
|
||||
|
||||
async_start();
|
||||
NodeButtonBrush* brush = new NodeButtonBrush;
|
||||
m_brush_popup->m_container->add_child(brush);
|
||||
brush->init();
|
||||
@@ -83,9 +78,6 @@ bool NodePanelStroke::import_abr(const std::string& path)
|
||||
count++;
|
||||
float prog = (float)count / (float)tot;
|
||||
pb->m_progress->SetWidthP(prog * 100.f);
|
||||
app_redraw();
|
||||
async_update();
|
||||
async_end();
|
||||
});
|
||||
m_brush_popup->save();
|
||||
|
||||
@@ -101,7 +93,6 @@ bool NodePanelStroke::import_abr(const std::string& path)
|
||||
auto thumb = patt.second->resize(64, 64);
|
||||
thumb.save(path_thumb);
|
||||
|
||||
async_start();
|
||||
NodeButtonBrush* brush = new NodeButtonBrush;
|
||||
m_pattern_popup->m_container->add_child(brush);
|
||||
brush->init();
|
||||
@@ -116,16 +107,12 @@ bool NodePanelStroke::import_abr(const std::string& path)
|
||||
count++;
|
||||
float prog = (float)count / (float)tot;
|
||||
pb->m_progress->SetWidthP(prog * 100.f);
|
||||
app_redraw();
|
||||
async_update();
|
||||
async_end();
|
||||
});
|
||||
m_pattern_popup->save();
|
||||
|
||||
auto brushes = abr.compute_brushes(App::I.data_path);
|
||||
for (const auto& pr : brushes)
|
||||
{
|
||||
async_start();
|
||||
if (pr->valid())
|
||||
{
|
||||
LOG("add preset %s", pr->m_name.c_str());
|
||||
@@ -134,17 +121,10 @@ bool NodePanelStroke::import_abr(const std::string& path)
|
||||
count++;
|
||||
float prog = (float)count / (float)tot;
|
||||
pb->m_progress->SetWidthP(prog * 100.f);
|
||||
app_redraw();
|
||||
async_update();
|
||||
async_end();
|
||||
}
|
||||
|
||||
async_start();
|
||||
App::I.presets->save();
|
||||
pb->destroy();
|
||||
app_redraw();
|
||||
async_update();
|
||||
async_end();
|
||||
//save();
|
||||
|
||||
return true;
|
||||
|
||||
@@ -264,6 +264,7 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
glm::mat4 ortho_proj = glm::ortho<float>(0, size.x, 0, size.y, -1, 1);
|
||||
glViewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
|
||||
m_rtt.bindFramebuffer();
|
||||
m_rtt.clear();
|
||||
m_sampler_mipmap.bind(0);
|
||||
m_sampler_linear.bind(1);
|
||||
m_sampler_linear_repeat.bind(2);
|
||||
|
||||
41
src/util.cpp
41
src/util.cpp
@@ -2,6 +2,7 @@
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
#include <poly2tri.h>
|
||||
#include "app.h"
|
||||
|
||||
template<>
|
||||
std::vector<vertex_t> poly_remove_duplicate<vertex_t>(const std::vector<vertex_t>& v, const float tollerance)
|
||||
@@ -714,3 +715,43 @@ void parallel_for(size_t nb_elements, std::function<void(size_t i)> functor, boo
|
||||
if (use_threads)
|
||||
std::for_each(my_threads.begin(), my_threads.end(), std::mem_fn(&std::thread::join));
|
||||
}
|
||||
|
||||
void gl_state::save()
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
blend = glIsEnabled(GL_BLEND);
|
||||
depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||
scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb);
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &active_tex);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &cube);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, tex + i);
|
||||
glGetIntegerv(GL_SAMPLER_BINDING, sampler + i);
|
||||
}
|
||||
}
|
||||
|
||||
void gl_state::restore()
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||
scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST);
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
glUseProgram(program);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glBindTexture(GL_TEXTURE_2D, tex[i]);
|
||||
glBindSampler(i, sampler[i]);
|
||||
}
|
||||
glActiveTexture(active_tex);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube);
|
||||
}
|
||||
|
||||
38
src/util.h
38
src/util.h
@@ -251,40 +251,6 @@ struct gl_state
|
||||
GLint fb;
|
||||
GLint active_tex;
|
||||
GLfloat line_width;
|
||||
void save()
|
||||
{
|
||||
blend = glIsEnabled(GL_BLEND);
|
||||
depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||
scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb);
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &active_tex);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &cube);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, tex + i);
|
||||
glGetIntegerv(GL_SAMPLER_BINDING, sampler + i);
|
||||
}
|
||||
}
|
||||
void restore()
|
||||
{
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
depth_test ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||
scissor_test ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST);
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
glUseProgram(program);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glBindTexture(GL_TEXTURE_2D, tex[i]);
|
||||
glBindSampler(i, sampler[i]);
|
||||
}
|
||||
glActiveTexture(active_tex);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube);
|
||||
}
|
||||
void save();
|
||||
void restore();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user